mirror of
https://github.com/UberGames/ioef.git
synced 2025-02-26 05:11:03 +00:00
New batch of fixes for the OpenAL part:
- Don't play sources outside the listening range (Thanks Kpaxian for bringing this to my attention) - Handle previously unhandled errors for old OpenAL sample implementation which does not support AL_SEC_OFFSET (sounds won't be synchronized then), thanks to Tequila from SmokingGuns for reporting this.
This commit is contained in:
parent
0ecfcfa872
commit
e345f9f81f
1 changed files with 181 additions and 85 deletions
|
@ -110,8 +110,10 @@ static void S_AL_ClearError( qboolean quiet )
|
||||||
if( quiet )
|
if( quiet )
|
||||||
return;
|
return;
|
||||||
if(error != AL_NO_ERROR)
|
if(error != AL_NO_ERROR)
|
||||||
|
{
|
||||||
Com_Printf(S_COLOR_YELLOW "WARNING: unhandled AL error: %s\n",
|
Com_Printf(S_COLOR_YELLOW "WARNING: unhandled AL error: %s\n",
|
||||||
S_AL_ErrorMsg(error));
|
S_AL_ErrorMsg(error));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -515,6 +517,7 @@ typedef struct src_s
|
||||||
#endif
|
#endif
|
||||||
static src_t srcList[MAX_SRC];
|
static src_t srcList[MAX_SRC];
|
||||||
static int srcCount = 0;
|
static int srcCount = 0;
|
||||||
|
static int srcActiveCnt = 0;
|
||||||
static qboolean alSourcesInitialised = qfalse;
|
static qboolean alSourcesInitialised = qfalse;
|
||||||
static vec3_t lastListenerOrigin = { 0.0f, 0.0f, 0.0f };
|
static vec3_t lastListenerOrigin = { 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
|
@ -637,6 +640,7 @@ qboolean S_AL_SrcInit( void )
|
||||||
// Clear the sources data structure
|
// Clear the sources data structure
|
||||||
memset(srcList, 0, sizeof(srcList));
|
memset(srcList, 0, sizeof(srcList));
|
||||||
srcCount = 0;
|
srcCount = 0;
|
||||||
|
srcActiveCnt = 0;
|
||||||
|
|
||||||
// Cap s_alSources to MAX_SRC
|
// Cap s_alSources to MAX_SRC
|
||||||
limit = s_alSources->integer;
|
limit = s_alSources->integer;
|
||||||
|
@ -670,6 +674,7 @@ static
|
||||||
void S_AL_SrcShutdown( void )
|
void S_AL_SrcShutdown( void )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
src_t *curSource;
|
||||||
|
|
||||||
if(!alSourcesInitialised)
|
if(!alSourcesInitialised)
|
||||||
return;
|
return;
|
||||||
|
@ -677,9 +682,14 @@ void S_AL_SrcShutdown( void )
|
||||||
// Destroy all the sources
|
// Destroy all the sources
|
||||||
for(i = 0; i < srcCount; i++)
|
for(i = 0; i < srcCount; i++)
|
||||||
{
|
{
|
||||||
if(srcList[i].isLocked)
|
curSource = &srcList[i];
|
||||||
|
|
||||||
|
if(curSource->isLocked)
|
||||||
Com_DPrintf( S_COLOR_YELLOW "WARNING: Source %d is locked\n", i);
|
Com_DPrintf( S_COLOR_YELLOW "WARNING: Source %d is locked\n", i);
|
||||||
|
|
||||||
|
if(curSource->entity > 0)
|
||||||
|
entityList[curSource->entity].srcAllocated = qfalse;
|
||||||
|
|
||||||
qalSourceStop(srcList[i].alSource);
|
qalSourceStop(srcList[i].alSource);
|
||||||
qalDeleteSources(1, &srcList[i].alSource);
|
qalDeleteSources(1, &srcList[i].alSource);
|
||||||
}
|
}
|
||||||
|
@ -712,7 +722,6 @@ static void S_AL_SrcSetup(srcHandle_t src, sfxHandle_t sfx, alSrcPriority_t prio
|
||||||
curSource->priority = priority;
|
curSource->priority = priority;
|
||||||
curSource->entity = entity;
|
curSource->entity = entity;
|
||||||
curSource->channel = channel;
|
curSource->channel = channel;
|
||||||
curSource->isActive = qtrue;
|
|
||||||
curSource->isPlaying = qfalse;
|
curSource->isPlaying = qfalse;
|
||||||
curSource->isLocked = qfalse;
|
curSource->isLocked = qfalse;
|
||||||
curSource->isLooping = qfalse;
|
curSource->isLooping = qfalse;
|
||||||
|
@ -749,6 +758,36 @@ Remove given source as loop master if it is the master and hand off master statu
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void S_AL_SaveLoopPos(src_t *dest, ALuint alSource)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
S_AL_ClearError(qfalse);
|
||||||
|
|
||||||
|
qalGetSourcef(alSource, AL_SEC_OFFSET, &dest->lastTimePos);
|
||||||
|
if((error = qalGetError()) != AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
// Old OpenAL implementations don't support AL_SEC_OFFSET
|
||||||
|
|
||||||
|
if(error != AL_INVALID_ENUM)
|
||||||
|
{
|
||||||
|
Com_Printf(S_COLOR_YELLOW "WARNING: Could not get time offset for alSource %d: %s\n",
|
||||||
|
alSource, S_AL_ErrorMsg(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
dest->lastTimePos = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dest->lastSampleTime = Sys_Milliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
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, qboolean iskilled)
|
static void S_AL_NewLoopMaster(src_t *rmSource, qboolean iskilled)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
@ -764,7 +803,16 @@ static void S_AL_NewLoopMaster(src_t *rmSource, qboolean iskilled)
|
||||||
|
|
||||||
if(curSfx->loopCnt)
|
if(curSfx->loopCnt)
|
||||||
{
|
{
|
||||||
if(rmSource == &srcList[curSfx->masterLoopSrc])
|
if(rmSource->priority == SRCPRI_ENTITY)
|
||||||
|
{
|
||||||
|
if(!iskilled && rmSource->isPlaying)
|
||||||
|
{
|
||||||
|
// only sync ambient loops...
|
||||||
|
// It makes more sense to have sounds for weapons/projectiles unsynced
|
||||||
|
S_AL_SaveLoopPos(rmSource, rmSource->alSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(rmSource == &srcList[curSfx->masterLoopSrc])
|
||||||
{
|
{
|
||||||
int firstInactive = -1;
|
int firstInactive = -1;
|
||||||
|
|
||||||
|
@ -778,7 +826,7 @@ static void S_AL_NewLoopMaster(src_t *rmSource, qboolean iskilled)
|
||||||
curSource = &srcList[index];
|
curSource = &srcList[index];
|
||||||
|
|
||||||
if(curSource->sfx == rmSource->sfx && curSource != rmSource &&
|
if(curSource->sfx == rmSource->sfx && curSource != rmSource &&
|
||||||
curSource->isActive && curSource->isLooping)
|
curSource->isActive && curSource->isLooping && curSource->priority == SRCPRI_AMBIENT)
|
||||||
{
|
{
|
||||||
if(curSource->isPlaying)
|
if(curSource->isPlaying)
|
||||||
{
|
{
|
||||||
|
@ -794,15 +842,22 @@ static void S_AL_NewLoopMaster(src_t *rmSource, qboolean iskilled)
|
||||||
if(!curSfx->loopActiveCnt)
|
if(!curSfx->loopActiveCnt)
|
||||||
{
|
{
|
||||||
if(firstInactive < 0)
|
if(firstInactive < 0)
|
||||||
curSource = rmSource;
|
{
|
||||||
|
if(iskilled)
|
||||||
|
{
|
||||||
|
curSfx->masterLoopSrc = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
curSource = rmSource;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
curSource = &srcList[firstInactive];
|
curSource = &srcList[firstInactive];
|
||||||
|
|
||||||
if(rmSource->isPlaying)
|
if(rmSource->isPlaying)
|
||||||
{
|
{
|
||||||
// this was the last not stopped source, save last sample position + time
|
// this was the last not stopped source, save last sample position + time
|
||||||
qalGetSourcef(rmSource->alSource, AL_SEC_OFFSET, &curSource->lastTimePos);
|
S_AL_SaveLoopPos(curSource, rmSource->alSource);
|
||||||
curSource->lastSampleTime = Sys_Milliseconds();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -865,7 +920,11 @@ static void S_AL_SrcKill(srcHandle_t src)
|
||||||
curSource->priority = 0;
|
curSource->priority = 0;
|
||||||
curSource->entity = -1;
|
curSource->entity = -1;
|
||||||
curSource->channel = -1;
|
curSource->channel = -1;
|
||||||
curSource->isActive = qfalse;
|
if(curSource->isActive)
|
||||||
|
{
|
||||||
|
curSource->isActive = qfalse;
|
||||||
|
srcActiveCnt--;
|
||||||
|
}
|
||||||
curSource->isLocked = qfalse;
|
curSource->isLocked = qfalse;
|
||||||
curSource->isTracking = qfalse;
|
curSource->isTracking = qfalse;
|
||||||
curSource->local = qfalse;
|
curSource->local = qfalse;
|
||||||
|
@ -884,6 +943,7 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel )
|
||||||
int weakest = -1;
|
int weakest = -1;
|
||||||
int weakest_time = Sys_Milliseconds();
|
int weakest_time = Sys_Milliseconds();
|
||||||
int weakest_pri = 999;
|
int weakest_pri = 999;
|
||||||
|
float weakest_gain = 1000.0;
|
||||||
qboolean weakest_isplaying = qtrue;
|
qboolean weakest_isplaying = qtrue;
|
||||||
int weakest_numloops = 0;
|
int weakest_numloops = 0;
|
||||||
src_t *curSource;
|
src_t *curSource;
|
||||||
|
@ -906,11 +966,15 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel )
|
||||||
if(curSource->isPlaying)
|
if(curSource->isPlaying)
|
||||||
{
|
{
|
||||||
if(weakest_isplaying && curSource->priority < priority &&
|
if(weakest_isplaying && curSource->priority < priority &&
|
||||||
(curSource->priority < weakest_pri || curSource->lastUsedTime < weakest_time))
|
(curSource->priority < weakest_pri ||
|
||||||
|
(!curSource->isLooping && (curSource->scaleGain < weakest_gain || curSource->lastUsedTime < weakest_time))))
|
||||||
{
|
{
|
||||||
// If it's older or has lower priority, flag it as weak
|
// If it has lower priority, is fainter or older, flag it as weak
|
||||||
|
// the last two values are only compared if it's not a looping sound, because we want to prevent two
|
||||||
|
// loops (loops are added EVERY frame) fighting for a slot
|
||||||
weakest_pri = curSource->priority;
|
weakest_pri = curSource->priority;
|
||||||
weakest_time = curSource->lastUsedTime;
|
weakest_time = curSource->lastUsedTime;
|
||||||
|
weakest_gain = curSource->scaleGain;
|
||||||
weakest = i;
|
weakest = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -918,7 +982,8 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel )
|
||||||
{
|
{
|
||||||
weakest_isplaying = qfalse;
|
weakest_isplaying = qfalse;
|
||||||
|
|
||||||
if(knownSfx[curSource->sfx].loopCnt > weakest_numloops ||
|
if(weakest < 0 ||
|
||||||
|
knownSfx[curSource->sfx].loopCnt > weakest_numloops ||
|
||||||
curSource->priority < weakest_pri ||
|
curSource->priority < weakest_pri ||
|
||||||
curSource->lastUsedTime < weakest_time)
|
curSource->lastUsedTime < weakest_time)
|
||||||
{
|
{
|
||||||
|
@ -928,7 +993,6 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel )
|
||||||
weakest_time = curSource->lastUsedTime;
|
weakest_time = curSource->lastUsedTime;
|
||||||
weakest_numloops = knownSfx[curSource->sfx].loopCnt;
|
weakest_numloops = knownSfx[curSource->sfx].loopCnt;
|
||||||
weakest = i;
|
weakest = i;
|
||||||
weakest_isplaying = qfalse;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,22 +1009,17 @@ srcHandle_t S_AL_SrcAlloc( alSrcPriority_t priority, int entnum, int channel )
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we have an empty one?
|
if(empty == -1)
|
||||||
if(empty != -1)
|
empty = weakest;
|
||||||
|
|
||||||
|
if(empty >= 0)
|
||||||
{
|
{
|
||||||
S_AL_SrcKill( empty );
|
S_AL_SrcKill(empty);
|
||||||
return empty;
|
srcList[empty].isActive = qtrue;
|
||||||
|
srcActiveCnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No. How about an overridable one?
|
return empty;
|
||||||
if(weakest != -1)
|
|
||||||
{
|
|
||||||
S_AL_SrcKill(weakest);
|
|
||||||
return weakest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing. Return failure (cries...)
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1040,7 +1099,7 @@ Necessary for i.g. Western Quake3 mod which is buggy.
|
||||||
static qboolean S_AL_CheckInput(int entityNum, sfxHandle_t sfx)
|
static qboolean S_AL_CheckInput(int entityNum, sfxHandle_t sfx)
|
||||||
{
|
{
|
||||||
if (entityNum < 0 || entityNum > MAX_GENTITIES)
|
if (entityNum < 0 || entityNum > MAX_GENTITIES)
|
||||||
Com_Error(ERR_DROP, "S_StartSound: bad entitynum %i", entityNum);
|
Com_Error(ERR_DROP, "ERROR: S_AL_CheckInput: bad entitynum %i", entityNum);
|
||||||
|
|
||||||
if (sfx < 0 || sfx >= numSfx)
|
if (sfx < 0 || sfx >= numSfx)
|
||||||
{
|
{
|
||||||
|
@ -1087,49 +1146,61 @@ S_AL_StartSound
|
||||||
Play a one-shot sound effect
|
Play a one-shot sound effect
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
static
|
static void S_AL_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx )
|
||||||
void S_AL_StartSound( vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx )
|
|
||||||
{
|
{
|
||||||
vec3_t sorigin;
|
vec3_t sorigin;
|
||||||
srcHandle_t src;
|
srcHandle_t src;
|
||||||
|
src_t *curSource;
|
||||||
|
|
||||||
if(S_AL_CheckInput(origin ? 0 : entnum, sfx))
|
if(origin)
|
||||||
|
{
|
||||||
|
if(S_AL_CheckInput(0, sfx))
|
||||||
|
return;
|
||||||
|
|
||||||
|
VectorCopy(origin, sorigin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(S_AL_CheckInput(entnum, sfx))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(S_AL_HearingThroughEntity(entnum))
|
||||||
|
{
|
||||||
|
S_AL_StartLocalSound(sfx, entchannel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorCopy(entityList[entnum].origin, sorigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
S_AL_SanitiseVector(sorigin);
|
||||||
|
|
||||||
|
if((srcActiveCnt > 5 * srcCount / 3) &&
|
||||||
|
(DistanceSquared(sorigin, lastListenerOrigin) >=
|
||||||
|
(s_alMaxDistance->value + s_alGraceDistance->value) * (s_alMaxDistance->value + s_alGraceDistance->value)))
|
||||||
|
{
|
||||||
|
// We're getting tight on sources and source is not within hearing distance so don't add it
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Try to grab a source
|
// Try to grab a source
|
||||||
src = S_AL_SrcAlloc(SRCPRI_ONESHOT, entnum, entchannel);
|
src = S_AL_SrcAlloc(SRCPRI_ONESHOT, entnum, entchannel);
|
||||||
if(src == -1)
|
if(src == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set up the effect
|
S_AL_SrcSetup(src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qfalse);
|
||||||
if( origin == NULL )
|
|
||||||
{
|
|
||||||
if( S_AL_HearingThroughEntity( entnum ) )
|
|
||||||
{
|
|
||||||
// Where the entity is the local player, play a local sound
|
|
||||||
S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qtrue );
|
|
||||||
VectorClear( sorigin );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qfalse );
|
|
||||||
VectorCopy( entityList[ entnum ].origin, sorigin );
|
|
||||||
}
|
|
||||||
srcList[ src ].isTracking = qtrue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
S_AL_SrcSetup( src, sfx, SRCPRI_ONESHOT, entnum, entchannel, qfalse );
|
|
||||||
VectorCopy( origin, sorigin );
|
|
||||||
}
|
|
||||||
|
|
||||||
S_AL_SanitiseVector( sorigin );
|
curSource = &srcList[src];
|
||||||
qalSourcefv( srcList[ src ].alSource, AL_POSITION, sorigin );
|
|
||||||
S_AL_ScaleGain(&srcList[src], sorigin);
|
if(!origin)
|
||||||
|
curSource->isTracking = qtrue;
|
||||||
|
|
||||||
|
qalSourcefv(curSource->alSource, AL_POSITION, sorigin );
|
||||||
|
S_AL_ScaleGain(curSource, sorigin);
|
||||||
|
|
||||||
// Start it playing
|
// Start it playing
|
||||||
srcList[src].isPlaying = qtrue;
|
curSource->isPlaying = qtrue;
|
||||||
qalSourcePlay(srcList[src].alSource);
|
qalSourcePlay(curSource->alSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1176,10 +1247,18 @@ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curSource = &srcList[src];
|
||||||
|
|
||||||
sent->startLoopingSound = qtrue;
|
sent->startLoopingSound = qtrue;
|
||||||
|
|
||||||
|
curSource->lastTimePos = -1.0;
|
||||||
|
curSource->lastSampleTime = Sys_Milliseconds();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
src = sent->srcIndex;
|
src = sent->srcIndex;
|
||||||
|
curSource = &srcList[src];
|
||||||
|
}
|
||||||
|
|
||||||
sent->srcAllocated = qtrue;
|
sent->srcAllocated = qtrue;
|
||||||
sent->srcIndex = src;
|
sent->srcIndex = src;
|
||||||
|
@ -1190,15 +1269,12 @@ static void S_AL_SrcLoop( alSrcPriority_t priority, sfxHandle_t sfx,
|
||||||
// If this is not set then the looping sound is stopped.
|
// If this is not set then the looping sound is stopped.
|
||||||
sent->loopAddedThisFrame = qtrue;
|
sent->loopAddedThisFrame = qtrue;
|
||||||
|
|
||||||
curSource = &srcList[src];
|
|
||||||
|
|
||||||
// UGH
|
// UGH
|
||||||
// These lines should be called via S_AL_SrcSetup, but we
|
// These lines should be called via S_AL_SrcSetup, but we
|
||||||
// can't call that yet as it buffers sfxes that may change
|
// can't call that yet as it buffers sfxes that may change
|
||||||
// with subsequent calls to S_AL_SrcLoop
|
// with subsequent calls to S_AL_SrcLoop
|
||||||
curSource->entity = entityNum;
|
curSource->entity = entityNum;
|
||||||
curSource->isLooping = qtrue;
|
curSource->isLooping = qtrue;
|
||||||
curSource->isActive = qtrue;
|
|
||||||
|
|
||||||
if( S_AL_HearingThroughEntity( entityNum ) )
|
if( S_AL_HearingThroughEntity( entityNum ) )
|
||||||
{
|
{
|
||||||
|
@ -1346,48 +1422,68 @@ void S_AL_SrcUpdate( void )
|
||||||
curSource->isPlaying = qfalse;
|
curSource->isPlaying = qfalse;
|
||||||
}
|
}
|
||||||
else if(!curSfx->loopActiveCnt && curSfx->masterLoopSrc < 0)
|
else if(!curSfx->loopActiveCnt && curSfx->masterLoopSrc < 0)
|
||||||
{
|
|
||||||
// There are no loops yet, make this one master
|
|
||||||
curSource->lastTimePos = 0;
|
|
||||||
curSource->lastSampleTime = Sys_Milliseconds();
|
|
||||||
|
|
||||||
curSfx->masterLoopSrc = i;
|
curSfx->masterLoopSrc = i;
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!curSource->isPlaying)
|
if(!curSource->isPlaying)
|
||||||
{
|
{
|
||||||
// If there are other looping sources with the same sound,
|
if(curSource->priority == SRCPRI_AMBIENT)
|
||||||
// make sure the sound of these sources are in sync.
|
|
||||||
|
|
||||||
if(curSfx->loopActiveCnt)
|
|
||||||
{
|
{
|
||||||
int offset;
|
// If there are other ambient looping sources with the same sound,
|
||||||
|
// make sure the sound of these sources are in sync.
|
||||||
|
|
||||||
// we already have a master loop playing, get buffer position.
|
if(curSfx->loopActiveCnt)
|
||||||
qalGetSourcei(srcList[curSfx->masterLoopSrc].alSource, AL_SAMPLE_OFFSET, &offset);
|
{
|
||||||
qalSourcei(curSource->alSource, AL_SAMPLE_OFFSET, offset);
|
int offset, error;
|
||||||
|
|
||||||
|
// we already have a master loop playing, get buffer position.
|
||||||
|
S_AL_ClearError(qfalse);
|
||||||
|
qalGetSourcei(srcList[curSfx->masterLoopSrc].alSource, AL_SAMPLE_OFFSET, &offset);
|
||||||
|
if((error = qalGetError()) != AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
if(error != AL_INVALID_ENUM)
|
||||||
|
{
|
||||||
|
Com_Printf(S_COLOR_YELLOW "WARNING: Cannot get sample offset from source %d: "
|
||||||
|
"%s\n", i, S_AL_ErrorMsg(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
qalSourcei(curSource->alSource, AL_SAMPLE_OFFSET, offset);
|
||||||
|
}
|
||||||
|
else if(curSfx->loopCnt && curSfx->masterLoopSrc >= 0)
|
||||||
|
{
|
||||||
|
float secofs;
|
||||||
|
|
||||||
|
src_t *master = &srcList[curSfx->masterLoopSrc];
|
||||||
|
// This loop sound used to be played, but all sources are stopped. Use last sample position/time
|
||||||
|
// to calculate offset so the player thinks the sources continued playing while they were inaudible.
|
||||||
|
|
||||||
|
if(master->lastTimePos >= 0)
|
||||||
|
{
|
||||||
|
secofs = master->lastTimePos + (Sys_Milliseconds() - master->lastSampleTime) / 1000.0f;
|
||||||
|
secofs = fmodf(secofs, (float) curSfx->info.samples / curSfx->info.rate);
|
||||||
|
|
||||||
|
qalSourcef(curSource->alSource, AL_SEC_OFFSET, secofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// I be the master now
|
||||||
|
curSfx->masterLoopSrc = i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
curSfx->masterLoopSrc = i;
|
||||||
}
|
}
|
||||||
else if(curSfx->loopCnt && curSfx->masterLoopSrc >= 0)
|
else if(curSource->lastTimePos >= 0)
|
||||||
{
|
{
|
||||||
float secofs;
|
float secofs;
|
||||||
|
|
||||||
src_t *master = &srcList[curSfx->masterLoopSrc];
|
// For unsynced loops (SRCPRI_ENTITY) just carry on playing as if the sound was never stopped
|
||||||
// This loop sound used to be played, but all sources are stopped. Use last sample position/time
|
|
||||||
// to calculate offset so the player thinks the sources continued playing while they were inaudible.
|
|
||||||
|
|
||||||
secofs = master->lastTimePos + (Sys_Milliseconds() - master->lastSampleTime) / 1000.0f;
|
secofs = curSource->lastTimePos + (Sys_Milliseconds() - curSource->lastSampleTime) / 1000.0f;
|
||||||
secofs = fmodf(secofs, (float) curSfx->info.samples / curSfx->info.rate);
|
secofs = fmodf(secofs, (float) curSfx->info.samples / curSfx->info.rate);
|
||||||
|
|
||||||
qalSourcef(curSource->alSource, AL_SEC_OFFSET, secofs);
|
qalSourcef(curSource->alSource, AL_SEC_OFFSET, secofs);
|
||||||
|
|
||||||
// I be the master now
|
|
||||||
curSfx->masterLoopSrc = i;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
curSfx->masterLoopSrc = i;
|
|
||||||
|
|
||||||
curSfx->loopActiveCnt++;
|
curSfx->loopActiveCnt++;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue