Misc OpenAL backend fixes

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6063 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Eukara 2021-09-16 20:08:30 +00:00
parent 156a629513
commit bca422ab08
1 changed files with 46 additions and 22 deletions

View File

@ -365,6 +365,8 @@ typedef struct
{ {
ALuint handle; ALuint handle;
qbyte allocated; //there is no guarenteed-unused handle (and I don't want to have to keep spamming alIsSource). qbyte allocated; //there is no guarenteed-unused handle (and I don't want to have to keep spamming alIsSource).
qbyte queuesize;
ALuint queue[3];
} *source; } *source;
size_t max_sources; size_t max_sources;
@ -644,6 +646,9 @@ static qboolean OpenAL_ReclaimASource(soundcardinfo_t *sc)
if (buf != AL_PLAYING) if (buf != AL_PLAYING)
{ {
palDeleteSources(1, &src); palDeleteSources(1, &src);
if (oali->source[i].queuesize)
palDeleteBuffers(oali->source[i].queuesize, oali->source[i].queue);
oali->source[i].queuesize = 0;
oali->source[i].handle = 0; oali->source[i].handle = 0;
oali->source[i].allocated = false; oali->source[i].allocated = false;
success++; success++;
@ -658,6 +663,9 @@ static qboolean OpenAL_ReclaimASource(soundcardinfo_t *sc)
if (oali->source[i].allocated) if (oali->source[i].allocated)
{ {
palDeleteSources(1, &oali->source[i].handle); palDeleteSources(1, &oali->source[i].handle);
if (oali->source[i].queuesize)
palDeleteBuffers(oali->source[i].queuesize, oali->source[i].queue);
oali->source[i].queuesize = 0;
oali->source[i].handle = 0; oali->source[i].handle = 0;
oali->source[i].allocated = false; oali->source[i].allocated = false;
success++; success++;
@ -697,6 +705,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
ALuint buf; ALuint buf;
qboolean stream; qboolean stream;
qboolean srcrel; qboolean srcrel;
ALuint processed;
if (chnum >= oali->max_sources) if (chnum >= oali->max_sources)
Z_ReallocElements((void**)&oali->source, &oali->max_sources, chnum+1+64, sizeof(*oali->source)); Z_ReallocElements((void**)&oali->source, &oali->max_sources, chnum+1+64, sizeof(*oali->source));
@ -739,22 +748,28 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
PrintALError("pre start sound"); PrintALError("pre start sound");
if (schanged&CUR_SOUNDCHANGE) if (schanged&CUR_SOUNDCHANGE)
palSourceStop(src);
//reclaim any queued buffers
palGetSourcei(src, AL_SOURCE_TYPE, &buf);
if (buf == AL_STREAMING)
{ {
for(;;) palSourceStop(src);
palSourcei(src, AL_BUFFER, 0);
if (oali->source[chnum].queuesize)
palDeleteBuffers(oali->source[chnum].queuesize, oali->source[chnum].queue);
oali->source[chnum].queuesize = 0;
}
else if (oali->source[chnum].queuesize)
{
//reclaim any queued buffers
palGetSourcei(src, AL_BUFFERS_PROCESSED, &processed);
if (processed)
{ {
palGetSourcei(src, AL_BUFFERS_PROCESSED, &buf); palSourceUnqueueBuffers(src, processed, oali->source[chnum].queue);
if (!buf) palDeleteBuffers(processed, oali->source[chnum].queue);
break; oali->source[chnum].queuesize -= processed;
palSourceUnqueueBuffers(src, 1, &buf); memmove(oali->source[chnum].queue, oali->source[chnum].queue+processed, oali->source[chnum].queuesize*sizeof(*oali->source[chnum].queue));
palDeleteBuffers(1, &buf);
} }
} }
else if (!schanged && sfx) //if we don't figure out when they've finished, they'll not get replaced properly.
if (!schanged && sfx) //if we don't figure out when they've finished, they'll not get replaced properly.
{ {
palGetSourcei(src, AL_SOURCE_STATE, &buf); palGetSourcei(src, AL_SOURCE_STATE, &buf);
if (buf != AL_PLAYING) if (buf != AL_PLAYING)
@ -778,6 +793,9 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
palSourceStop(src); palSourceStop(src);
#else #else
palDeleteSources(1, &src); palDeleteSources(1, &src);
if (oali->source[chnum].queuesize)
palDeleteBuffers(oali->source[chnum].queuesize, oali->source[chnum].queue);
oali->source[chnum].queuesize = 0;
oali->source[chnum].handle = 0; oali->source[chnum].handle = 0;
oali->source[chnum].allocated = false; oali->source[chnum].allocated = false;
#endif #endif
@ -793,7 +811,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
//openal doesn't support loopstart (entire sample loops or not at all), so if we're meant to skip the first half then we need to stream it. //openal doesn't support loopstart (entire sample loops or not at all), so if we're meant to skip the first half then we need to stream it.
stream = sfx->decoder.decodedata || sfx->loopstart > 0; stream = sfx->decoder.decodedata || sfx->loopstart > 0;
if (schanged || stream) if (schanged & CUR_SOUNDCHANGE || stream)
{ {
int sndnum = sfx-known_sfx; int sndnum = sfx-known_sfx;
int buf; int buf;
@ -814,13 +832,12 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
} }
return; //not available yet return; //not available yet
} }
if (stream) if (stream)
{ {
ALuint queuedbufs;
int offset; int offset;
sfxcache_t sbuf, *sc; sfxcache_t sbuf, *sc;
palGetSourcei(src, AL_BUFFERS_QUEUED, &queuedbufs); while (oali->source[chnum].queuesize < countof(oali->source[chnum].queue))
while (queuedbufs < 3)
{ //decode periodically instead of all at the start. { //decode periodically instead of all at the start.
int tryduration = snd_speed*0.5; int tryduration = snd_speed*0.5;
ssamplepos_t pos = chan->pos>>PITCHSHIFT; ssamplepos_t pos = chan->pos>>PITCHSHIFT;
@ -856,7 +873,10 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
//build a buffer with it and queue it up. //build a buffer with it and queue it up.
//buffer will be purged later on when its unqueued //buffer will be purged later on when its unqueued
if (OpenAL_LoadCache(oali, &buf, &sbuf, max(1,cvolume))) if (OpenAL_LoadCache(oali, &buf, &sbuf, max(1,cvolume)))
{
palSourceQueueBuffers(src, 1, &buf); palSourceQueueBuffers(src, 1, &buf);
oali->source[chnum].queue[oali->source[chnum].queuesize++] = buf;
}
} }
else else
{ //decoder isn't ready yet, but didn't signal an error/eof. queue a little silence, because that's better than constant micro stutters { //decoder isn't ready yet, but didn't signal an error/eof. queue a little silence, because that's better than constant micro stutters
@ -868,9 +888,11 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
silence.length = 0.1 * silence.speed; silence.length = 0.1 * silence.speed;
silence.soundoffset = 0; silence.soundoffset = 0;
if (OpenAL_LoadCache(oali, &buf, &silence, 1)) if (OpenAL_LoadCache(oali, &buf, &silence, 1))
{
palSourceQueueBuffers(src, 1, &buf); palSourceQueueBuffers(src, 1, &buf);
oali->source[chnum].queue[oali->source[chnum].queuesize++] = buf;
}
} }
queuedbufs++;
//yay //yay
chan->pos += sbuf.length<<PITCHSHIFT; chan->pos += sbuf.length<<PITCHSHIFT;
@ -887,7 +909,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
chan->pos = 0; chan->pos = 0;
else //we don't want to play anything more. else //we don't want to play anything more.
break; break;
if (!queuedbufs) if (!oali->source[chnum].queuesize)
{ //queue 0.1 secs if we're starting/resetting a new stream this is to try to cover up discontinuities caused by packetloss or whatever { //queue 0.1 secs if we're starting/resetting a new stream this is to try to cover up discontinuities caused by packetloss or whatever
sfxcache_t silence; sfxcache_t silence;
silence.speed = snd_speed; silence.speed = snd_speed;
@ -897,12 +919,14 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
silence.length = 0.1 * silence.speed; silence.length = 0.1 * silence.speed;
silence.soundoffset = 0; silence.soundoffset = 0;
if (OpenAL_LoadCache(oali, &buf, &silence, 1)) if (OpenAL_LoadCache(oali, &buf, &silence, 1))
{
palSourceQueueBuffers(src, 1, &buf); palSourceQueueBuffers(src, 1, &buf);
queuedbufs++; oali->source[chnum].queue[oali->source[chnum].queuesize++] = buf;
}
} }
} }
} }
if (!queuedbufs) if (!oali->source[chnum].queuesize)
{ {
palGetSourcei(src, AL_SOURCE_STATE, &buf); palGetSourcei(src, AL_SOURCE_STATE, &buf);
if (buf != AL_PLAYING) if (buf != AL_PLAYING)
@ -981,7 +1005,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
} }
#endif #endif
palSourcei(src, AL_LOOPING, (!stream && (chan->flags & CF_FORCELOOP))?AL_TRUE:AL_FALSE); palSourcei(src, AL_LOOPING, (!stream && ((chan->flags & CF_FORCELOOP)||sfx->loopstart==0))?AL_TRUE:AL_FALSE);
if (srcrel) if (srcrel)
{ {
palSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE); palSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
@ -1059,7 +1083,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
palSourcePlay(src); palSourcePlay(src);
} }
PrintALError("post start sound"); PrintALError(sfx&&sfx->name?sfx->name:"post start sound");
} }
/* /*