diff options
author | Chris Robinson <[email protected]> | 2019-03-09 16:48:07 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-03-09 16:48:07 -0800 |
commit | ef0f3351321a7488e60faa838a4628cfecf230b8 (patch) | |
tree | a28d31d1eb4fdf785a6f2fceeaa7cface4a02973 /Alc/mixvoice.cpp | |
parent | cde4500e24a8f5067d87711bf778cde99f26d990 (diff) |
Add a Stopping state for voices
This currently doesn't do much, except have the mixer progress it to Stopped.
It's valid to have without a source or buffers, and in the future will allow
fading out when a source is paused or stopped.
Diffstat (limited to 'Alc/mixvoice.cpp')
-rw-r--r-- | Alc/mixvoice.cpp | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/Alc/mixvoice.cpp b/Alc/mixvoice.cpp index 2cc26d7b..9602ac72 100644 --- a/Alc/mixvoice.cpp +++ b/Alc/mixvoice.cpp @@ -198,6 +198,23 @@ void aluInitMixer() namespace { +void SendSourceStoppedEvent(ALCcontext *context, ALuint id) +{ + ALbitfieldSOFT enabledevt{context->EnabledEvts.load(std::memory_order_acquire)}; + if(!(enabledevt&EventType_SourceStateChange)) return; + + RingBuffer *ring{context->AsyncEvents.get()}; + auto evt_vec = ring->getWriteVector(); + if(evt_vec.first.len < 1) return; + + AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}}; + evt->u.srcstate.id = id; + evt->u.srcstate.state = AL_STOPPED; + + ring->writeAdvance(1); + context->EventSem.post(); +} + /* Base template left undefined. Should be marked =delete, but Clang 3.8.1 * chokes on that given the inline specializations. */ @@ -283,20 +300,20 @@ const ALfloat *DoFilters(BiquadFilter *lpfilter, BiquadFilter *hpfilter, } // namespace -ALboolean MixSource(ALvoice *voice, const ALuint SourceID, ALCcontext *Context, const ALsizei SamplesToDo) +void MixSource(ALvoice *voice, const ALuint SourceID, ALCcontext *Context, const ALsizei SamplesToDo) { ASSUME(SamplesToDo > 0); /* Get source info */ - bool isplaying{true}; /* Will only be called while playing. */ - bool isstatic{(voice->Flags&VOICE_IS_STATIC) != 0}; - ALsizei DataPosInt{static_cast<ALsizei>(voice->position.load(std::memory_order_acquire))}; + ALvoice::State vstate{voice->PlayState.load(std::memory_order_acquire)}; + const bool isstatic{(voice->Flags&VOICE_IS_STATIC) != 0}; + ALsizei DataPosInt{static_cast<ALsizei>(voice->position.load(std::memory_order_relaxed))}; ALsizei DataPosFrac{voice->position_fraction.load(std::memory_order_relaxed)}; ALbufferlistitem *BufferListItem{voice->current_buffer.load(std::memory_order_relaxed)}; ALbufferlistitem *BufferLoopItem{voice->loop_buffer.load(std::memory_order_relaxed)}; - ALsizei NumChannels{voice->NumChannels}; - ALsizei SampleSize{voice->SampleSize}; - ALint increment{voice->Step}; + const ALsizei NumChannels{voice->NumChannels}; + const ALsizei SampleSize{voice->SampleSize}; + const ALint increment{voice->Step}; ASSUME(DataPosInt >= 0); ASSUME(DataPosFrac >= 0); @@ -304,6 +321,15 @@ ALboolean MixSource(ALvoice *voice, const ALuint SourceID, ALCcontext *Context, ASSUME(SampleSize > 0); ASSUME(increment > 0); + /* TODO: Use stored previous samples to fade out without incrementing when + * stopping (buffers may not be available). + */ + if(UNLIKELY(vstate == ALvoice::Stopping)) + { + voice->PlayState.store(ALvoice::Stopped, std::memory_order_release); + return; + } + ALCdevice *Device{Context->Device}; const ALsizei IrSize{Device->mHrtf ? Device->mHrtf->irSize : 0}; const int OutLIdx{GetChannelIdxByName(Device->RealOut, FrontLeft)}; @@ -704,7 +730,7 @@ ALboolean MixSource(ALvoice *voice, const ALuint SourceID, ALCcontext *Context, /* Handle non-looping static source */ if(DataPosInt >= BufferListItem->max_samples) { - isplaying = false; + vstate = ALvoice::Stopped; BufferListItem = nullptr; DataPosInt = 0; DataPosFrac = 0; @@ -724,13 +750,13 @@ ALboolean MixSource(ALvoice *voice, const ALuint SourceID, ALCcontext *Context, BufferListItem = BufferListItem->next.load(std::memory_order_relaxed); if(!BufferListItem && !(BufferListItem=BufferLoopItem)) { - isplaying = false; + vstate = ALvoice::Stopped; DataPosInt = 0; DataPosFrac = 0; break; } } - } while(isplaying && OutPos < SamplesToDo); + } while(vstate != ALvoice::Stopped && OutPos < SamplesToDo); voice->Flags |= VOICE_IS_FADING; @@ -755,5 +781,12 @@ ALboolean MixSource(ALvoice *voice, const ALuint SourceID, ALCcontext *Context, } } - return isplaying; + if(vstate == ALvoice::Stopped) + { + voice->current_buffer.store(nullptr, std::memory_order_relaxed); + voice->loop_buffer.store(nullptr, std::memory_order_relaxed); + voice->SourceID.store(0u, std::memory_order_relaxed); + voice->PlayState.store(ALvoice::Stopped, std::memory_order_release); + SendSourceStoppedEvent(Context, SourceID); + } } |