Ensure a non-playing or -paused source does not use a mixing voice
This commit is contained in:
@@ -1427,7 +1427,10 @@ void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
source = (*voice)->Source;
|
||||
if(IsVoiceInit && source &&
|
||||
ATOMIC_LOAD(&source->state, almemory_order_relaxed) == AL_PLAYING)
|
||||
MixSource(*voice, source, device, SamplesToDo);
|
||||
{
|
||||
if(!MixSource(*voice, source, device, SamplesToDo))
|
||||
(*voice)->Source = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* effect slot processing */
|
||||
|
||||
+2
-1
@@ -366,7 +366,7 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
|
||||
}
|
||||
|
||||
|
||||
void MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo)
|
||||
ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo)
|
||||
{
|
||||
ResamplerFunc Resample;
|
||||
ALbufferlistitem *BufferListItem;
|
||||
@@ -685,4 +685,5 @@ void MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei Samp
|
||||
ATOMIC_STORE(&Source->current_buffer, BufferListItem, almemory_order_relaxed);
|
||||
ATOMIC_STORE(&Source->position, DataPosInt, almemory_order_relaxed);
|
||||
ATOMIC_STORE(&Source->position_fraction, DataPosFrac, almemory_order_release);
|
||||
return State == AL_PLAYING;
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
+58
-46
@@ -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,61 +2977,68 @@ 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;
|
||||
}
|
||||
|
||||
// Check if an Offset has been set
|
||||
if(Source->OffsetType != AL_NONE)
|
||||
{
|
||||
ApplyOffset(Source);
|
||||
/* discontinuity = AL_TRUE;??? */
|
||||
}
|
||||
|
||||
/* If there's nothing to play, or device is disconnected, go right to
|
||||
* stopped */
|
||||
/* If there's nothing to play, or the device is disconnected, go right
|
||||
* to stopped.
|
||||
*/
|
||||
if(!BufferList || !device->Connected)
|
||||
goto do_stop;
|
||||
|
||||
voice = GetSourceVoice(Source, Context);
|
||||
switch(ATOMIC_EXCHANGE(ALenum, &Source->state, AL_PLAYING, almemory_order_acq_rel))
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
assert(voice == NULL);
|
||||
for(i = 0;i < Context->VoiceCount;i++)
|
||||
{
|
||||
if(Context->Voices[i]->Source == NULL)
|
||||
{
|
||||
voice = Context->Voices[i];
|
||||
voice->Source = Source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(voice == NULL)
|
||||
{
|
||||
for(i = 0;i < Context->VoiceCount;i++)
|
||||
{
|
||||
if(Context->Voices[i]->Source == NULL)
|
||||
{
|
||||
voice = Context->Voices[i];
|
||||
voice->Source = Source;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(voice == NULL)
|
||||
{
|
||||
voice = Context->Voices[Context->VoiceCount++];
|
||||
voice->Source = Source;
|
||||
}
|
||||
discontinuity = AL_TRUE;
|
||||
voice = Context->Voices[Context->VoiceCount++];
|
||||
voice->Source = Source;
|
||||
}
|
||||
|
||||
if(discontinuity)
|
||||
{
|
||||
/* Clear previous samples if playback is discontinuous. */
|
||||
memset(voice->PrevSamples, 0, sizeof(voice->PrevSamples));
|
||||
/* 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;
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user