diff options
-rw-r--r-- | Alc/ALu.c | 5 | ||||
-rw-r--r-- | Alc/mixer.c | 3 | ||||
-rw-r--r-- | OpenAL32/Include/alu.h | 2 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 98 |
4 files changed, 62 insertions, 46 deletions
@@ -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 */ diff --git a/Alc/mixer.c b/Alc/mixer.c index 46ca0892..be09ed67 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -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; } 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); } |