aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-02-25 16:46:30 -0800
committerChris Robinson <[email protected]>2017-02-25 18:10:09 -0800
commit513c18fdc4d0d9184e061570209eb59f4ad0e392 (patch)
treebe71c303104b0dd998acd3be69211be580705952 /OpenAL32
parent9539ccc18be1ddda6ef32c2d4bd4c15b4ed4115c (diff)
Ensure a non-playing or -paused source does not use a mixing voice
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/Include/alu.h2
-rw-r--r--OpenAL32/alSource.c98
2 files changed, 56 insertions, 44 deletions
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 326cde62..b6f0e769 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -348,7 +348,7 @@ void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans,
void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
-void MixSource(struct ALvoice *voice, struct ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo);
+ALboolean MixSource(struct ALvoice *voice, struct ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo);
void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
/* Caller must lock the device. */
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index bb70a056..1fc2c5bd 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -2957,13 +2957,13 @@ void UpdateAllSourceProps(ALCcontext *context)
*/
ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
{
+ ALvoice *voice;
+
WriteLock(&Source->queue_lock);
if(state == AL_PLAYING)
{
ALCdevice *device = Context->Device;
ALbufferlistitem *BufferList;
- ALboolean discontinuity;
- ALvoice *voice = NULL;
ALsizei i;
/* Check that there is a queue containing at least one valid, non zero
@@ -2977,62 +2977,69 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
BufferList = BufferList->next;
}
- if(ATOMIC_EXCHANGE(ALenum, &Source->state, AL_PLAYING, almemory_order_acq_rel) == AL_PAUSED)
- discontinuity = AL_FALSE;
- else
- {
- ATOMIC_STORE(&Source->current_buffer, BufferList, almemory_order_relaxed);
- ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed);
- ATOMIC_STORE(&Source->position_fraction, 0, almemory_order_release);
- discontinuity = AL_TRUE;
- }
+ /* If there's nothing to play, or the device is disconnected, go right
+ * to stopped.
+ */
+ if(!BufferList || !device->Connected)
+ goto do_stop;
- // Check if an Offset has been set
- if(Source->OffsetType != AL_NONE)
+ voice = GetSourceVoice(Source, Context);
+ switch(ATOMIC_EXCHANGE(ALenum, &Source->state, AL_PLAYING, almemory_order_acq_rel))
{
- ApplyOffset(Source);
- /* discontinuity = AL_TRUE;??? */
- }
+ case AL_PLAYING:
+ /* A source that's already playing is restarted. */
+ ATOMIC_STORE(&Source->current_buffer, BufferList, almemory_order_relaxed);
+ ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed);
+ ATOMIC_STORE(&Source->position_fraction, 0, almemory_order_release);
+ /* fall-through */
+ case AL_PAUSED:
+ /* A source that's paused simply resumes. Make sure it uses the
+ * volume last specified; there's no reason to fade from where
+ * it stopped at.
+ */
+ assert(voice != NULL);
+ voice->Moving = AL_FALSE;
+ goto done;
- /* If there's nothing to play, or device is disconnected, go right to
- * stopped */
- if(!BufferList || !device->Connected)
- goto do_stop;
+ default:
+ /* A source that's not playing or paused has its offset
+ * applied, and then starts playing.
+ */
+ ATOMIC_STORE(&Source->current_buffer, BufferList, almemory_order_relaxed);
+ ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed);
+ ATOMIC_STORE(&Source->position_fraction, 0, almemory_order_release);
+ if(Source->OffsetType != AL_NONE)
+ ApplyOffset(Source);
+ break;
+ }
/* Make sure this source isn't already active, and if not, look for an
* unused voice to put it in.
*/
- voice = GetSourceVoice(Source, Context);
- if(voice == NULL)
+ assert(voice == NULL);
+ for(i = 0;i < Context->VoiceCount;i++)
{
- for(i = 0;i < Context->VoiceCount;i++)
- {
- if(Context->Voices[i]->Source == NULL)
- {
- voice = Context->Voices[i];
- voice->Source = Source;
- break;
- }
- }
- if(voice == NULL)
+ if(Context->Voices[i]->Source == NULL)
{
- voice = Context->Voices[Context->VoiceCount++];
+ voice = Context->Voices[i];
voice->Source = Source;
+ break;
}
- discontinuity = AL_TRUE;
}
-
- if(discontinuity)
+ if(voice == NULL)
{
- /* Clear previous samples if playback is discontinuous. */
- memset(voice->PrevSamples, 0, sizeof(voice->PrevSamples));
-
- /* Clear the stepping value so the mixer knows not to mix this
- * until the update gets applied.
- */
- voice->Step = 0;
+ voice = Context->Voices[Context->VoiceCount++];
+ voice->Source = Source;
}
+ /* Clear previous samples. */
+ memset(voice->PrevSamples, 0, sizeof(voice->PrevSamples));
+
+ /* Clear the stepping value so the mixer knows not to mix this until
+ * the update gets applied.
+ */
+ voice->Step = 0;
+
voice->Moving = AL_FALSE;
for(i = 0;i < MAX_INPUT_CHANNELS;i++)
{
@@ -3057,6 +3064,8 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
else if(state == AL_STOPPED)
{
do_stop:
+ voice = GetSourceVoice(Source, Context);
+ if(voice) voice->Source = NULL;
if(ATOMIC_LOAD(&Source->state, almemory_order_acquire) != AL_INITIAL)
{
ATOMIC_STORE(&Source->state, AL_STOPPED, almemory_order_relaxed);
@@ -3067,6 +3076,8 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
}
else if(state == AL_INITIAL)
{
+ voice = GetSourceVoice(Source, Context);
+ if(voice) voice->Source = NULL;
if(ATOMIC_LOAD(&Source->state, almemory_order_acquire) != AL_INITIAL)
{
ATOMIC_STORE(&Source->state, AL_INITIAL, almemory_order_relaxed);
@@ -3078,6 +3089,7 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
Source->OffsetType = AL_NONE;
Source->Offset = 0.0;
}
+done:
WriteUnlock(&Source->queue_lock);
}