diff options
Diffstat (limited to 'al')
-rw-r--r-- | al/source.cpp | 2512 | ||||
-rw-r--r-- | al/source.h | 16 |
2 files changed, 1266 insertions, 1262 deletions
diff --git a/al/source.cpp b/al/source.cpp index d368b3f0..3c22b620 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -74,6 +74,7 @@ namespace { using namespace std::placeholders; +using std::chrono::nanoseconds; ALvoice *GetSourceVoice(ALsource *source, ALCcontext *context) { @@ -175,7 +176,7 @@ void UpdateSourceProps(const ALsource *source, ALvoice *voice, ALCcontext *conte * samples. The offset is relative to the start of the queue (not the start of * the current buffer). */ -int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, std::chrono::nanoseconds *clocktime) +int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds *clocktime) { ALCdevice *device{context->mDevice.get()}; const ALbufferlistitem *Current; @@ -221,7 +222,7 @@ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, std::chrono * Gets the current read offset for the given Source, in seconds. The offset is * relative to the start of the queue (not the start of the current buffer). */ -ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, std::chrono::nanoseconds *clocktime) +ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *clocktime) { ALCdevice *device{context->mDevice.get()}; const ALbufferlistitem *Current; @@ -465,49 +466,72 @@ al::optional<VoicePos> GetSampleOffset(ALsource *Source) } -ALsource *AllocSource(ALCcontext *context) +/** + * Returns if the last known state for the source was playing or paused. Does + * not sync with the mixer voice. + */ +inline bool IsPlayingOrPaused(ALsource *source) +{ return source->state == AL_PLAYING || source->state == AL_PAUSED; } + +/** + * Returns an updated source state using the matching voice's status (or lack + * thereof). + */ +inline ALenum GetSourceState(ALsource *source, ALvoice *voice) { - ALCdevice *device{context->mDevice.get()}; - std::lock_guard<std::mutex> _{context->mSourceLock}; - if(context->mNumSources >= device->SourcesMax) - { - context->setError(AL_OUT_OF_MEMORY, "Exceeding %u source limit", device->SourcesMax); - return nullptr; - } - auto sublist = std::find_if(context->mSourceList.begin(), context->mSourceList.end(), - [](const SourceSubList &entry) noexcept -> bool - { return entry.FreeMask != 0; } - ); - auto lidx = static_cast<ALsizei>(std::distance(context->mSourceList.begin(), sublist)); - ALsizei slidx; - if LIKELY(sublist != context->mSourceList.end()) - slidx = CTZ64(sublist->FreeMask); - else + if(!voice && source->state == AL_PLAYING) + source->state = AL_STOPPED; + return source->state; +} + +/** + * Returns if the source should specify an update, given the context's + * deferring state and the source's last known state. + */ +inline bool SourceShouldUpdate(ALsource *source, ALCcontext *context) +{ + return !context->mDeferUpdates.load(std::memory_order_acquire) && + IsPlayingOrPaused(source); +} + + +bool EnsureSources(ALCcontext *context, size_t needed) +{ + size_t count{std::accumulate(context->mSourceList.cbegin(), context->mSourceList.cend(), + size_t{0}, + [](size_t cur, const SourceSubList &sublist) noexcept -> size_t + { return cur + static_cast<ALuint>(POPCNT64(~sublist.FreeMask)); } + )}; + + while(needed > count) { - /* Don't allocate so many list entries that the 32-bit ID could - * overflow... - */ if UNLIKELY(context->mSourceList.size() >= 1<<25) - { - context->setError(AL_OUT_OF_MEMORY, "Too many sources allocated"); - return nullptr; - } - context->mSourceList.emplace_back(); - sublist = context->mSourceList.end() - 1; + return false; + context->mSourceList.emplace_back(); + auto sublist = context->mSourceList.end() - 1; sublist->FreeMask = ~0_u64; - sublist->Sources = static_cast<ALsource*>(al_calloc(16, sizeof(ALsource)*64)); + sublist->Sources = static_cast<ALsource*>(al_calloc(alignof(ALsource), sizeof(ALsource)*64)); if UNLIKELY(!sublist->Sources) { context->mSourceList.pop_back(); - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate source batch"); - return nullptr; + return false; } - - slidx = 0; + count += 64; } + return true; +} - ALsource *source{::new (sublist->Sources + slidx) ALsource{device->NumAuxSends}}; +ALsource *AllocSource(ALCcontext *context, ALsizei num_sends) +{ + auto sublist = std::find_if(context->mSourceList.begin(), context->mSourceList.end(), + [](const SourceSubList &entry) noexcept -> bool + { return entry.FreeMask != 0; } + ); + auto lidx = static_cast<ALuint>(std::distance(context->mSourceList.begin(), sublist)); + auto slidx = static_cast<ALuint>(CTZ64(sublist->FreeMask)); + + ALsource *source{::new (sublist->Sources + slidx) ALsource{num_sends}}; /* Add 1 to avoid source ID 0. */ source->id = ((lidx<<6) | slidx) + 1; @@ -520,26 +544,28 @@ ALsource *AllocSource(ALCcontext *context) void FreeSource(ALCcontext *context, ALsource *source) { - ALuint id = source->id - 1; - ALsizei lidx = id >> 6; - ALsizei slidx = id & 0x3f; + const ALuint id{source->id - 1}; + const size_t lidx{id >> 6}; + const ALuint slidx{id & 0x3f}; - ALCdevice *device{context->mDevice.get()}; - BackendUniqueLock backlock{*device->Backend}; - if(ALvoice *voice{GetSourceVoice(source, context)}) - { - voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed); - voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed); - voice->mSourceID.store(0u, std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_release); - /* Don't set the voice to stopping if it was already stopped or - * stopping. - */ - ALvoice::State oldvstate{ALvoice::Playing}; - voice->mPlayState.compare_exchange_strong(oldvstate, ALvoice::Stopping, - std::memory_order_acq_rel, std::memory_order_acquire); + if(IsPlayingOrPaused(source)) + { + ALCdevice *device{context->mDevice.get()}; + BackendLockGuard _{*device->Backend}; + if(ALvoice *voice{GetSourceVoice(source, context)}) + { + voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed); + voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed); + voice->mSourceID.store(0u, std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + /* Don't set the voice to stopping if it was already stopped or + * stopping. + */ + ALvoice::State oldvstate{ALvoice::Playing}; + voice->mPlayState.compare_exchange_strong(oldvstate, ALvoice::Stopping, + std::memory_order_acq_rel, std::memory_order_acquire); + } } - backlock.unlock(); al::destroy_at(source); @@ -550,8 +576,8 @@ void FreeSource(ALCcontext *context, ALsource *source) inline ALsource *LookupSource(ALCcontext *context, ALuint id) noexcept { - ALuint lidx = (id-1) >> 6; - ALsizei slidx = (id-1) & 0x3f; + const size_t lidx{(id-1) >> 6}; + const ALuint slidx{(id-1) & 0x3f}; if UNLIKELY(lidx >= context->mSourceList.size()) return nullptr; @@ -563,8 +589,8 @@ inline ALsource *LookupSource(ALCcontext *context, ALuint id) noexcept inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) noexcept { - ALuint lidx = (id-1) >> 6; - ALsizei slidx = (id-1) & 0x3f; + const size_t lidx{(id-1) >> 6}; + const ALuint slidx{(id-1) & 0x3f}; if UNLIKELY(lidx >= device->BufferList.size()) return nullptr; @@ -576,8 +602,8 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) noexcept inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) noexcept { - ALuint lidx = (id-1) >> 6; - ALsizei slidx = (id-1) & 0x3f; + const size_t lidx{(id-1) >> 6}; + const ALuint slidx{(id-1) & 0x3f}; if UNLIKELY(lidx >= device->FilterList.size()) return nullptr; @@ -589,8 +615,8 @@ inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) noexcept inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id) noexcept { - ALuint lidx = (id-1) >> 6; - ALsizei slidx = (id-1) & 0x3f; + const size_t lidx{(id-1) >> 6}; + const ALuint slidx{(id-1) & 0x3f}; if UNLIKELY(lidx >= context->mEffectSlotList.size()) return nullptr; @@ -669,34 +695,6 @@ enum SourceProp : ALenum { srcSecOffsetClockSOFT = AL_SEC_OFFSET_CLOCK_SOFT, }; -/** - * Returns if the last known state for the source was playing or paused. Does - * not sync with the mixer voice. - */ -inline bool IsPlayingOrPaused(ALsource *source) -{ return source->state == AL_PLAYING || source->state == AL_PAUSED; } - -/** - * Returns an updated source state using the matching voice's status (or lack - * thereof). - */ -inline ALenum GetSourceState(ALsource *source, ALvoice *voice) -{ - if(!voice && source->state == AL_PLAYING) - source->state = AL_STOPPED; - return source->state; -} - -/** - * Returns if the source should specify an update, given the context's - * deferring state and the source's last known state. - */ -inline bool SourceShouldUpdate(ALsource *source, ALCcontext *context) -{ - return !context->mDeferUpdates.load(std::memory_order_acquire) && - IsPlayingOrPaused(source); -} - /** Can only be called while the mixer is locked! */ void SendStateChangeEvent(ALCcontext *context, ALuint id, ALenum state) @@ -712,7 +710,7 @@ void SendStateChangeEvent(ALCcontext *context, ALuint id, ALenum state) auto evt_vec = ring->getWriteVector(); if(evt_vec.first.len < 1) return; - AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}}; + AsyncEvent *evt{::new (evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}}; evt->u.srcstate.id = id; evt->u.srcstate.state = state; ring->writeAdvance(1); @@ -726,61 +724,61 @@ ALuint FloatValsByProp(ALenum prop) { switch(static_cast<SourceProp>(prop)) { - case AL_PITCH: - case AL_GAIN: - case AL_MIN_GAIN: - case AL_MAX_GAIN: - case AL_MAX_DISTANCE: - case AL_ROLLOFF_FACTOR: - case AL_DOPPLER_FACTOR: - case AL_CONE_OUTER_GAIN: - case AL_SEC_OFFSET: - case AL_SAMPLE_OFFSET: - case AL_BYTE_OFFSET: - case AL_CONE_INNER_ANGLE: - case AL_CONE_OUTER_ANGLE: - case AL_REFERENCE_DISTANCE: - case AL_CONE_OUTER_GAINHF: - case AL_AIR_ABSORPTION_FACTOR: - case AL_ROOM_ROLLOFF_FACTOR: - case AL_DIRECT_FILTER_GAINHF_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: - case AL_DIRECT_CHANNELS_SOFT: - case AL_DISTANCE_MODEL: - case AL_SOURCE_RELATIVE: - case AL_LOOPING: - case AL_SOURCE_STATE: - case AL_BUFFERS_QUEUED: - case AL_BUFFERS_PROCESSED: - case AL_SOURCE_TYPE: - case AL_SOURCE_RADIUS: - case AL_SOURCE_RESAMPLER_SOFT: - case AL_SOURCE_SPATIALIZE_SOFT: - return 1; - - case AL_STEREO_ANGLES: - return 2; - - case AL_POSITION: - case AL_VELOCITY: - case AL_DIRECTION: - return 3; - - case AL_ORIENTATION: - return 6; - - case AL_SEC_OFFSET_LATENCY_SOFT: - case AL_SEC_OFFSET_CLOCK_SOFT: - break; /* Double only */ - - case AL_BUFFER: - case AL_DIRECT_FILTER: - case AL_AUXILIARY_SEND_FILTER: - break; /* i/i64 only */ - case AL_SAMPLE_OFFSET_LATENCY_SOFT: - case AL_SAMPLE_OFFSET_CLOCK_SOFT: - break; /* i64 only */ + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_SOURCE_RADIUS: + case AL_SOURCE_RESAMPLER_SOFT: + case AL_SOURCE_SPATIALIZE_SOFT: + return 1; + + case AL_STEREO_ANGLES: + return 2; + + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + return 3; + + case AL_ORIENTATION: + return 6; + + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_CLOCK_SOFT: + break; /* Double only */ + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + break; /* i/i64 only */ + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SAMPLE_OFFSET_CLOCK_SOFT: + break; /* i64 only */ } return 0; } @@ -788,59 +786,59 @@ ALuint DoubleValsByProp(ALenum prop) { switch(static_cast<SourceProp>(prop)) { - case AL_PITCH: - case AL_GAIN: - case AL_MIN_GAIN: - case AL_MAX_GAIN: - case AL_MAX_DISTANCE: - case AL_ROLLOFF_FACTOR: - case AL_DOPPLER_FACTOR: - case AL_CONE_OUTER_GAIN: - case AL_SEC_OFFSET: - case AL_SAMPLE_OFFSET: - case AL_BYTE_OFFSET: - case AL_CONE_INNER_ANGLE: - case AL_CONE_OUTER_ANGLE: - case AL_REFERENCE_DISTANCE: - case AL_CONE_OUTER_GAINHF: - case AL_AIR_ABSORPTION_FACTOR: - case AL_ROOM_ROLLOFF_FACTOR: - case AL_DIRECT_FILTER_GAINHF_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: - case AL_DIRECT_CHANNELS_SOFT: - case AL_DISTANCE_MODEL: - case AL_SOURCE_RELATIVE: - case AL_LOOPING: - case AL_SOURCE_STATE: - case AL_BUFFERS_QUEUED: - case AL_BUFFERS_PROCESSED: - case AL_SOURCE_TYPE: - case AL_SOURCE_RADIUS: - case AL_SOURCE_RESAMPLER_SOFT: - case AL_SOURCE_SPATIALIZE_SOFT: - return 1; - - case AL_SEC_OFFSET_LATENCY_SOFT: - case AL_SEC_OFFSET_CLOCK_SOFT: - case AL_STEREO_ANGLES: - return 2; - - case AL_POSITION: - case AL_VELOCITY: - case AL_DIRECTION: - return 3; - - case AL_ORIENTATION: - return 6; - - case AL_BUFFER: - case AL_DIRECT_FILTER: - case AL_AUXILIARY_SEND_FILTER: - break; /* i/i64 only */ - case AL_SAMPLE_OFFSET_LATENCY_SOFT: - case AL_SAMPLE_OFFSET_CLOCK_SOFT: - break; /* i64 only */ + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_SOURCE_RADIUS: + case AL_SOURCE_RESAMPLER_SOFT: + case AL_SOURCE_SPATIALIZE_SOFT: + return 1; + + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_CLOCK_SOFT: + case AL_STEREO_ANGLES: + return 2; + + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + return 3; + + case AL_ORIENTATION: + return 6; + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + break; /* i/i64 only */ + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SAMPLE_OFFSET_CLOCK_SOFT: + break; /* i64 only */ } return 0; } @@ -879,222 +877,222 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a switch(prop) { - case AL_SEC_OFFSET_LATENCY_SOFT: - case AL_SEC_OFFSET_CLOCK_SOFT: - /* Query only */ - SETERR_RETURN(Context, AL_INVALID_OPERATION, false, - "Setting read-only source property 0x%04x", prop); + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_CLOCK_SOFT: + /* Query only */ + SETERR_RETURN(Context, AL_INVALID_OPERATION, false, + "Setting read-only source property 0x%04x", prop); - case AL_PITCH: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f); + case AL_PITCH: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f); - Source->Pitch = values[0]; - return UpdateSourceProps(Source, Context); + Source->Pitch = values[0]; + return UpdateSourceProps(Source, Context); - case AL_CONE_INNER_ANGLE: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f && values[0] <= 360.0f); + case AL_CONE_INNER_ANGLE: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f && values[0] <= 360.0f); - Source->InnerAngle = values[0]; - return UpdateSourceProps(Source, Context); + Source->InnerAngle = values[0]; + return UpdateSourceProps(Source, Context); - case AL_CONE_OUTER_ANGLE: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f && values[0] <= 360.0f); + case AL_CONE_OUTER_ANGLE: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f && values[0] <= 360.0f); - Source->OuterAngle = values[0]; - return UpdateSourceProps(Source, Context); + Source->OuterAngle = values[0]; + return UpdateSourceProps(Source, Context); - case AL_GAIN: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f); + case AL_GAIN: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f); - Source->Gain = values[0]; - return UpdateSourceProps(Source, Context); + Source->Gain = values[0]; + return UpdateSourceProps(Source, Context); - case AL_MAX_DISTANCE: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f); + case AL_MAX_DISTANCE: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f); - Source->MaxDistance = values[0]; - return UpdateSourceProps(Source, Context); + Source->MaxDistance = values[0]; + return UpdateSourceProps(Source, Context); - case AL_ROLLOFF_FACTOR: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f); + case AL_ROLLOFF_FACTOR: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f); - Source->RolloffFactor = values[0]; - return UpdateSourceProps(Source, Context); + Source->RolloffFactor = values[0]; + return UpdateSourceProps(Source, Context); - case AL_REFERENCE_DISTANCE: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f); + case AL_REFERENCE_DISTANCE: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f); - Source->RefDistance = values[0]; - return UpdateSourceProps(Source, Context); + Source->RefDistance = values[0]; + return UpdateSourceProps(Source, Context); - case AL_MIN_GAIN: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f); + case AL_MIN_GAIN: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f); - Source->MinGain = values[0]; - return UpdateSourceProps(Source, Context); + Source->MinGain = values[0]; + return UpdateSourceProps(Source, Context); - case AL_MAX_GAIN: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f); + case AL_MAX_GAIN: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f); - Source->MaxGain = values[0]; - return UpdateSourceProps(Source, Context); + Source->MaxGain = values[0]; + return UpdateSourceProps(Source, Context); - case AL_CONE_OUTER_GAIN: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f && values[0] <= 1.0f); + case AL_CONE_OUTER_GAIN: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f && values[0] <= 1.0f); - Source->OuterGain = values[0]; - return UpdateSourceProps(Source, Context); + Source->OuterGain = values[0]; + return UpdateSourceProps(Source, Context); - case AL_CONE_OUTER_GAINHF: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f && values[0] <= 1.0f); + case AL_CONE_OUTER_GAINHF: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f && values[0] <= 1.0f); - Source->OuterGainHF = values[0]; - return UpdateSourceProps(Source, Context); + Source->OuterGainHF = values[0]; + return UpdateSourceProps(Source, Context); - case AL_AIR_ABSORPTION_FACTOR: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f && values[0] <= 10.0f); + case AL_AIR_ABSORPTION_FACTOR: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f && values[0] <= 10.0f); - Source->AirAbsorptionFactor = values[0]; - return UpdateSourceProps(Source, Context); + Source->AirAbsorptionFactor = values[0]; + return UpdateSourceProps(Source, Context); - case AL_ROOM_ROLLOFF_FACTOR: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f && values[0] <= 10.0f); + case AL_ROOM_ROLLOFF_FACTOR: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f && values[0] <= 10.0f); - Source->RoomRolloffFactor = values[0]; - return UpdateSourceProps(Source, Context); + Source->RoomRolloffFactor = values[0]; + return UpdateSourceProps(Source, Context); - case AL_DOPPLER_FACTOR: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f && values[0] <= 1.0f); + case AL_DOPPLER_FACTOR: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f && values[0] <= 1.0f); - Source->DopplerFactor = values[0]; - return UpdateSourceProps(Source, Context); + Source->DopplerFactor = values[0]; + return UpdateSourceProps(Source, Context); - case AL_SEC_OFFSET: - case AL_SAMPLE_OFFSET: - case AL_BYTE_OFFSET: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f); + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f); - Source->OffsetType = prop; - Source->Offset = values[0]; + Source->OffsetType = prop; + Source->Offset = values[0]; - if(IsPlayingOrPaused(Source)) + if(IsPlayingOrPaused(Source)) + { + ALCdevice *device{Context->mDevice.get()}; + BackendLockGuard _{*device->Backend}; + /* Double-check that the source is still playing while we have the + * lock. + */ + if(ALvoice *voice{GetSourceVoice(Source, Context)}) { - ALCdevice *device{Context->mDevice.get()}; - BackendLockGuard _{*device->Backend}; - /* Double-check that the source is still playing while we have - * the lock. - */ - if(ALvoice *voice{GetSourceVoice(Source, Context)}) - { - auto vpos = GetSampleOffset(Source); - if(!vpos) SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid offset"); - - voice->mPosition.store(vpos->pos, std::memory_order_relaxed); - voice->mPositionFrac.store(vpos->frac, std::memory_order_relaxed); - voice->mCurrentBuffer.store(vpos->bufferitem, std::memory_order_release); - } - } - return true; + auto vpos = GetSampleOffset(Source); + if(!vpos) SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid offset"); - case AL_SOURCE_RADIUS: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0.0f && std::isfinite(values[0])); - - Source->Radius = values[0]; - return UpdateSourceProps(Source, Context); - - case AL_STEREO_ANGLES: - CHECKSIZE(values, 2); - CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1])); - - Source->StereoPan[0] = values[0]; - Source->StereoPan[1] = values[1]; - return UpdateSourceProps(Source, Context); - - - case AL_POSITION: - CHECKSIZE(values, 3); - CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])); - - Source->Position[0] = values[0]; - Source->Position[1] = values[1]; - Source->Position[2] = values[2]; - return UpdateSourceProps(Source, Context); - - case AL_VELOCITY: - CHECKSIZE(values, 3); - CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])); - - Source->Velocity[0] = values[0]; - Source->Velocity[1] = values[1]; - Source->Velocity[2] = values[2]; - return UpdateSourceProps(Source, Context); - - case AL_DIRECTION: - CHECKSIZE(values, 3); - CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])); - - Source->Direction[0] = values[0]; - Source->Direction[1] = values[1]; - Source->Direction[2] = values[2]; - return UpdateSourceProps(Source, Context); - - case AL_ORIENTATION: - CHECKSIZE(values, 6); - CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]) && - std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5])); - - Source->OrientAt[0] = values[0]; - Source->OrientAt[1] = values[1]; - Source->OrientAt[2] = values[2]; - Source->OrientUp[0] = values[3]; - Source->OrientUp[1] = values[4]; - Source->OrientUp[2] = values[5]; - return UpdateSourceProps(Source, Context); - - - case AL_SOURCE_RELATIVE: - case AL_LOOPING: - case AL_SOURCE_STATE: - case AL_SOURCE_TYPE: - case AL_DISTANCE_MODEL: - case AL_DIRECT_FILTER_GAINHF_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: - case AL_DIRECT_CHANNELS_SOFT: - case AL_SOURCE_RESAMPLER_SOFT: - case AL_SOURCE_SPATIALIZE_SOFT: - CHECKSIZE(values, 1); - ival = static_cast<ALint>(values[0]); - return SetSourceiv(Source, Context, prop, {&ival, 1u}); - - case AL_BUFFERS_QUEUED: - case AL_BUFFERS_PROCESSED: - CHECKSIZE(values, 1); - ival = static_cast<ALint>(static_cast<ALuint>(values[0])); - return SetSourceiv(Source, Context, prop, {&ival, 1u}); - - case AL_BUFFER: - case AL_DIRECT_FILTER: - case AL_AUXILIARY_SEND_FILTER: - case AL_SAMPLE_OFFSET_LATENCY_SOFT: - case AL_SAMPLE_OFFSET_CLOCK_SOFT: - break; + voice->mPosition.store(vpos->pos, std::memory_order_relaxed); + voice->mPositionFrac.store(vpos->frac, std::memory_order_relaxed); + voice->mCurrentBuffer.store(vpos->bufferitem, std::memory_order_release); + } + } + return true; + + case AL_SOURCE_RADIUS: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0.0f && std::isfinite(values[0])); + + Source->Radius = values[0]; + return UpdateSourceProps(Source, Context); + + case AL_STEREO_ANGLES: + CHECKSIZE(values, 2); + CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1])); + + Source->StereoPan[0] = values[0]; + Source->StereoPan[1] = values[1]; + return UpdateSourceProps(Source, Context); + + + case AL_POSITION: + CHECKSIZE(values, 3); + CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])); + + Source->Position[0] = values[0]; + Source->Position[1] = values[1]; + Source->Position[2] = values[2]; + return UpdateSourceProps(Source, Context); + + case AL_VELOCITY: + CHECKSIZE(values, 3); + CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])); + + Source->Velocity[0] = values[0]; + Source->Velocity[1] = values[1]; + Source->Velocity[2] = values[2]; + return UpdateSourceProps(Source, Context); + + case AL_DIRECTION: + CHECKSIZE(values, 3); + CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2])); + + Source->Direction[0] = values[0]; + Source->Direction[1] = values[1]; + Source->Direction[2] = values[2]; + return UpdateSourceProps(Source, Context); + + case AL_ORIENTATION: + CHECKSIZE(values, 6); + CHECKVAL(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]) + && std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5])); + + Source->OrientAt[0] = values[0]; + Source->OrientAt[1] = values[1]; + Source->OrientAt[2] = values[2]; + Source->OrientUp[0] = values[3]; + Source->OrientUp[1] = values[4]; + Source->OrientUp[2] = values[5]; + return UpdateSourceProps(Source, Context); + + + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_SOURCE_TYPE: + case AL_DISTANCE_MODEL: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_SOURCE_RESAMPLER_SOFT: + case AL_SOURCE_SPATIALIZE_SOFT: + CHECKSIZE(values, 1); + ival = static_cast<ALint>(values[0]); + return SetSourceiv(Source, Context, prop, {&ival, 1u}); + + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + CHECKSIZE(values, 1); + ival = static_cast<ALint>(static_cast<ALuint>(values[0])); + return SetSourceiv(Source, Context, prop, {&ival, 1u}); + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SAMPLE_OFFSET_CLOCK_SOFT: + break; } ERR("Unexpected property: 0x%04x\n", prop); @@ -1116,304 +1114,308 @@ bool SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a switch(prop) { - case AL_SOURCE_STATE: - case AL_SOURCE_TYPE: - case AL_BUFFERS_QUEUED: - case AL_BUFFERS_PROCESSED: - /* Query only */ - SETERR_RETURN(Context, AL_INVALID_OPERATION, false, - "Setting read-only source property 0x%04x", prop); - - case AL_SOURCE_RELATIVE: - CHECKSIZE(values, 1); - CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); - - Source->HeadRelative = static_cast<ALboolean>(values[0]); - return UpdateSourceProps(Source, Context); - - case AL_LOOPING: - CHECKSIZE(values, 1); - CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); - - Source->Looping = static_cast<ALboolean>(values[0]); - if(IsPlayingOrPaused(Source)) + case AL_SOURCE_STATE: + case AL_SOURCE_TYPE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + /* Query only */ + SETERR_RETURN(Context, AL_INVALID_OPERATION, false, + "Setting read-only source property 0x%04x", prop); + + case AL_SOURCE_RELATIVE: + CHECKSIZE(values, 1); + CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); + + Source->HeadRelative = static_cast<ALboolean>(values[0]); + return UpdateSourceProps(Source, Context); + + case AL_LOOPING: + CHECKSIZE(values, 1); + CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); + + Source->Looping = static_cast<ALboolean>(values[0]); + if(IsPlayingOrPaused(Source)) + { + if(ALvoice *voice{GetSourceVoice(Source, Context)}) { - if(ALvoice *voice{GetSourceVoice(Source, Context)}) - { - if(Source->Looping) - voice->mLoopBuffer.store(Source->queue, std::memory_order_release); - else - voice->mLoopBuffer.store(nullptr, std::memory_order_release); - - /* If the source is playing, wait for the current mix to finish - * to ensure it isn't currently looping back or reaching the - * end. - */ - while((device->MixCount.load(std::memory_order_acquire)&1)) - std::this_thread::yield(); - } + if(Source->Looping) + voice->mLoopBuffer.store(Source->queue, std::memory_order_release); + else + voice->mLoopBuffer.store(nullptr, std::memory_order_release); + + /* If the source is playing, wait for the current mix to finish + * to ensure it isn't currently looping back or reaching the + * end. + */ + while((device->MixCount.load(std::memory_order_acquire)&1)) + std::this_thread::yield(); } - return true; + } + return true; - case AL_BUFFER: - CHECKSIZE(values, 1); - buflock = std::unique_lock<std::mutex>{device->BufferLock}; - if(!(values[0] == 0 || (buffer=LookupBuffer(device, values[0])) != nullptr)) - SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid buffer ID %u", values[0]); + case AL_BUFFER: + CHECKSIZE(values, 1); + buflock = std::unique_lock<std::mutex>{device->BufferLock}; + if(values[0] && (buffer=LookupBuffer(device, static_cast<ALuint>(values[0]))) == nullptr) + SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid buffer ID %u", + static_cast<ALuint>(values[0])); - if(buffer && buffer->MappedAccess != 0 && - !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) + if(buffer && buffer->MappedAccess != 0 && + !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) + SETERR_RETURN(Context, AL_INVALID_OPERATION, false, + "Setting non-persistently mapped buffer %u", buffer->id); + else + { + ALenum state = GetSourceState(Source, GetSourceVoice(Source, Context)); + if(state == AL_PLAYING || state == AL_PAUSED) SETERR_RETURN(Context, AL_INVALID_OPERATION, false, - "Setting non-persistently mapped buffer %u", buffer->id); - else - { - ALenum state = GetSourceState(Source, GetSourceVoice(Source, Context)); - if(state == AL_PLAYING || state == AL_PAUSED) - SETERR_RETURN(Context, AL_INVALID_OPERATION, false, - "Setting buffer on playing or paused source %u", Source->id); - } + "Setting buffer on playing or paused source %u", Source->id); + } - oldlist = Source->queue; - if(buffer != nullptr) - { - /* Add the selected buffer to a one-item queue */ - auto newlist = new ALbufferlistitem{}; - newlist->mSampleLen = buffer->SampleLen; - newlist->mBuffer = buffer; - IncrementRef(buffer->ref); - - /* Source is now Static */ - Source->SourceType = AL_STATIC; - Source->queue = newlist; - } - else - { - /* Source is now Undetermined */ - Source->SourceType = AL_UNDETERMINED; - Source->queue = nullptr; - } - buflock.unlock(); + oldlist = Source->queue; + if(buffer != nullptr) + { + /* Add the selected buffer to a one-item queue */ + auto newlist = new ALbufferlistitem{}; + newlist->mSampleLen = buffer->SampleLen; + newlist->mBuffer = buffer; + IncrementRef(buffer->ref); + + /* Source is now Static */ + Source->SourceType = AL_STATIC; + Source->queue = newlist; + } + else + { + /* Source is now Undetermined */ + Source->SourceType = AL_UNDETERMINED; + Source->queue = nullptr; + } + buflock.unlock(); - /* Delete all elements in the previous queue */ - while(oldlist != nullptr) - { - std::unique_ptr<ALbufferlistitem> temp{oldlist}; - oldlist = temp->mNext.load(std::memory_order_relaxed); + /* Delete all elements in the previous queue */ + while(oldlist != nullptr) + { + std::unique_ptr<ALbufferlistitem> temp{oldlist}; + oldlist = temp->mNext.load(std::memory_order_relaxed); - if(ALbuffer *buffer{temp->mBuffer}) - DecrementRef(buffer->ref); - } - return true; + if(ALbuffer *buffer{temp->mBuffer}) + DecrementRef(buffer->ref); + } + return true; - case AL_SEC_OFFSET: - case AL_SAMPLE_OFFSET: - case AL_BYTE_OFFSET: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0); + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0); - Source->OffsetType = prop; - Source->Offset = values[0]; + Source->OffsetType = prop; + Source->Offset = values[0]; - if(IsPlayingOrPaused(Source)) + if(IsPlayingOrPaused(Source)) + { + ALCdevice *device{Context->mDevice.get()}; + BackendLockGuard _{*device->Backend}; + if(ALvoice *voice{GetSourceVoice(Source, Context)}) { - ALCdevice *device{Context->mDevice.get()}; - BackendLockGuard _{*device->Backend}; - if(ALvoice *voice{GetSourceVoice(Source, Context)}) - { - auto vpos = GetSampleOffset(Source); - if(!vpos) SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid source offset"); - - voice->mPosition.store(vpos->pos, std::memory_order_relaxed); - voice->mPositionFrac.store(vpos->frac, std::memory_order_relaxed); - voice->mCurrentBuffer.store(vpos->bufferitem, std::memory_order_release); - } - } - return true; - - case AL_DIRECT_FILTER: - CHECKSIZE(values, 1); - filtlock = std::unique_lock<std::mutex>{device->FilterLock}; - if(!(values[0] == 0 || (filter=LookupFilter(device, values[0])) != nullptr)) - SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid filter ID %u", values[0]); + auto vpos = GetSampleOffset(Source); + if(!vpos) SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid source offset"); - if(!filter) - { - Source->Direct.Gain = 1.0f; - Source->Direct.GainHF = 1.0f; - Source->Direct.HFReference = LOWPASSFREQREF; - Source->Direct.GainLF = 1.0f; - Source->Direct.LFReference = HIGHPASSFREQREF; + voice->mPosition.store(vpos->pos, std::memory_order_relaxed); + voice->mPositionFrac.store(vpos->frac, std::memory_order_relaxed); + voice->mCurrentBuffer.store(vpos->bufferitem, std::memory_order_release); } - else - { - Source->Direct.Gain = filter->Gain; - Source->Direct.GainHF = filter->GainHF; - Source->Direct.HFReference = filter->HFReference; - Source->Direct.GainLF = filter->GainLF; - Source->Direct.LFReference = filter->LFReference; - } - filtlock.unlock(); - return UpdateSourceProps(Source, Context); + } + return true; - case AL_DIRECT_FILTER_GAINHF_AUTO: - CHECKSIZE(values, 1); - CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); + case AL_DIRECT_FILTER: + CHECKSIZE(values, 1); + filtlock = std::unique_lock<std::mutex>{device->FilterLock}; + if(values[0] && (filter=LookupFilter(device, static_cast<ALuint>(values[0]))) == nullptr) + SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid filter ID %u", + static_cast<ALuint>(values[0])); - Source->DryGainHFAuto = values[0]; - return UpdateSourceProps(Source, Context); + if(!filter) + { + Source->Direct.Gain = 1.0f; + Source->Direct.GainHF = 1.0f; + Source->Direct.HFReference = LOWPASSFREQREF; + Source->Direct.GainLF = 1.0f; + Source->Direct.LFReference = HIGHPASSFREQREF; + } + else + { + Source->Direct.Gain = filter->Gain; + Source->Direct.GainHF = filter->GainHF; + Source->Direct.HFReference = filter->HFReference; + Source->Direct.GainLF = filter->GainLF; + Source->Direct.LFReference = filter->LFReference; + } + filtlock.unlock(); + return UpdateSourceProps(Source, Context); - case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: - CHECKSIZE(values, 1); - CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); + case AL_DIRECT_FILTER_GAINHF_AUTO: + CHECKSIZE(values, 1); + CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); - Source->WetGainAuto = values[0]; - return UpdateSourceProps(Source, Context); + Source->DryGainHFAuto = values[0]; + return UpdateSourceProps(Source, Context); - case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: - CHECKSIZE(values, 1); - CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + CHECKSIZE(values, 1); + CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); - Source->WetGainHFAuto = values[0]; - return UpdateSourceProps(Source, Context); + Source->WetGainAuto = values[0]; + return UpdateSourceProps(Source, Context); - case AL_DIRECT_CHANNELS_SOFT: - CHECKSIZE(values, 1); - CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + CHECKSIZE(values, 1); + CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); - Source->DirectChannels = values[0]; - return UpdateSourceProps(Source, Context); + Source->WetGainHFAuto = values[0]; + return UpdateSourceProps(Source, Context); - case AL_DISTANCE_MODEL: - CHECKSIZE(values, 1); - CHECKVAL(values[0] == AL_NONE || - values[0] == AL_INVERSE_DISTANCE || values[0] == AL_INVERSE_DISTANCE_CLAMPED || - values[0] == AL_LINEAR_DISTANCE || values[0] == AL_LINEAR_DISTANCE_CLAMPED || - values[0] == AL_EXPONENT_DISTANCE || values[0] == AL_EXPONENT_DISTANCE_CLAMPED); + case AL_DIRECT_CHANNELS_SOFT: + CHECKSIZE(values, 1); + CHECKVAL(values[0] == AL_FALSE || values[0] == AL_TRUE); - Source->mDistanceModel = static_cast<DistanceModel>(values[0]); - if(Context->mSourceDistanceModel) - return UpdateSourceProps(Source, Context); - return true; + Source->DirectChannels = values[0]; + return UpdateSourceProps(Source, Context); - case AL_SOURCE_RESAMPLER_SOFT: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= 0 && values[0] <= ResamplerMax); + case AL_DISTANCE_MODEL: + CHECKSIZE(values, 1); + CHECKVAL(values[0] == AL_NONE || + values[0] == AL_INVERSE_DISTANCE || values[0] == AL_INVERSE_DISTANCE_CLAMPED || + values[0] == AL_LINEAR_DISTANCE || values[0] == AL_LINEAR_DISTANCE_CLAMPED || + values[0] == AL_EXPONENT_DISTANCE || values[0] == AL_EXPONENT_DISTANCE_CLAMPED); - Source->mResampler = static_cast<Resampler>(values[0]); + Source->mDistanceModel = static_cast<DistanceModel>(values[0]); + if(Context->mSourceDistanceModel) return UpdateSourceProps(Source, Context); + return true; - case AL_SOURCE_SPATIALIZE_SOFT: - CHECKSIZE(values, 1); - CHECKVAL(values[0] >= AL_FALSE && values[0] <= AL_AUTO_SOFT); + case AL_SOURCE_RESAMPLER_SOFT: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= 0 && values[0] <= ResamplerMax); - Source->mSpatialize = static_cast<SpatializeMode>(values[0]); - return UpdateSourceProps(Source, Context); + Source->mResampler = static_cast<Resampler>(values[0]); + return UpdateSourceProps(Source, Context); + case AL_SOURCE_SPATIALIZE_SOFT: + CHECKSIZE(values, 1); + CHECKVAL(values[0] >= AL_FALSE && values[0] <= AL_AUTO_SOFT); - case AL_AUXILIARY_SEND_FILTER: - CHECKSIZE(values, 3); - slotlock = std::unique_lock<std::mutex>{Context->mEffectSlotLock}; - if(!(values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != nullptr)) - SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid effect ID %u", values[0]); - if(static_cast<ALuint>(values[1]) >= static_cast<ALuint>(device->NumAuxSends)) - SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid send %u", values[1]); + Source->mSpatialize = static_cast<SpatializeMode>(values[0]); + return UpdateSourceProps(Source, Context); - filtlock = std::unique_lock<std::mutex>{device->FilterLock}; - if(!(values[2] == 0 || (filter=LookupFilter(device, values[2])) != nullptr)) - SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid filter ID %u", values[2]); - if(!filter) - { - /* Disable filter */ - Source->Send[values[1]].Gain = 1.0f; - Source->Send[values[1]].GainHF = 1.0f; - Source->Send[values[1]].HFReference = LOWPASSFREQREF; - Source->Send[values[1]].GainLF = 1.0f; - Source->Send[values[1]].LFReference = HIGHPASSFREQREF; - } - else - { - Source->Send[values[1]].Gain = filter->Gain; - Source->Send[values[1]].GainHF = filter->GainHF; - Source->Send[values[1]].HFReference = filter->HFReference; - Source->Send[values[1]].GainLF = filter->GainLF; - Source->Send[values[1]].LFReference = filter->LFReference; - } - filtlock.unlock(); + case AL_AUXILIARY_SEND_FILTER: + CHECKSIZE(values, 3); + slotlock = std::unique_lock<std::mutex>{Context->mEffectSlotLock}; + if(values[0] && (slot=LookupEffectSlot(Context, static_cast<ALuint>(values[0]))) == nullptr) + SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid effect ID %u", values[0]); + if(static_cast<ALuint>(values[1]) >= static_cast<ALuint>(device->NumAuxSends)) + SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid send %u", values[1]); - if(slot != Source->Send[values[1]].Slot && IsPlayingOrPaused(Source)) - { - /* Add refcount on the new slot, and release the previous slot */ - if(slot) IncrementRef(slot->ref); - if(Source->Send[values[1]].Slot) - DecrementRef(Source->Send[values[1]].Slot->ref); - Source->Send[values[1]].Slot = slot; - - /* We must force an update if the auxiliary slot changed on an - * active source, in case the slot is about to be deleted. - */ - ALvoice *voice{GetSourceVoice(Source, Context)}; - if(voice) UpdateSourceProps(Source, voice, Context); - else Source->PropsClean.clear(std::memory_order_release); - } - else - { - if(slot) IncrementRef(slot->ref); - if(Source->Send[values[1]].Slot) - DecrementRef(Source->Send[values[1]].Slot->ref); - Source->Send[values[1]].Slot = slot; - UpdateSourceProps(Source, Context); - } - return true; - - - /* 1x float */ - case AL_CONE_INNER_ANGLE: - case AL_CONE_OUTER_ANGLE: - case AL_PITCH: - case AL_GAIN: - case AL_MIN_GAIN: - case AL_MAX_GAIN: - case AL_REFERENCE_DISTANCE: - case AL_ROLLOFF_FACTOR: - case AL_CONE_OUTER_GAIN: - case AL_MAX_DISTANCE: - case AL_DOPPLER_FACTOR: - case AL_CONE_OUTER_GAINHF: - case AL_AIR_ABSORPTION_FACTOR: - case AL_ROOM_ROLLOFF_FACTOR: - case AL_SOURCE_RADIUS: - CHECKSIZE(values, 1); - fvals[0] = static_cast<ALfloat>(values[0]); - return SetSourcefv(Source, Context, prop, {fvals, 1u}); - - /* 3x float */ - case AL_POSITION: - case AL_VELOCITY: - case AL_DIRECTION: - CHECKSIZE(values, 3); - fvals[0] = static_cast<ALfloat>(values[0]); - fvals[1] = static_cast<ALfloat>(values[1]); - fvals[2] = static_cast<ALfloat>(values[2]); - return SetSourcefv(Source, Context, prop, {fvals, 3u}); - - /* 6x float */ - case AL_ORIENTATION: - CHECKSIZE(values, 6); - fvals[0] = static_cast<ALfloat>(values[0]); - fvals[1] = static_cast<ALfloat>(values[1]); - fvals[2] = static_cast<ALfloat>(values[2]); - fvals[3] = static_cast<ALfloat>(values[3]); - fvals[4] = static_cast<ALfloat>(values[4]); - fvals[5] = static_cast<ALfloat>(values[5]); - return SetSourcefv(Source, Context, prop, {fvals, 6u}); - - case AL_SAMPLE_OFFSET_LATENCY_SOFT: - case AL_SEC_OFFSET_LATENCY_SOFT: - case AL_SEC_OFFSET_CLOCK_SOFT: - case AL_SAMPLE_OFFSET_CLOCK_SOFT: - case AL_STEREO_ANGLES: - break; + filtlock = std::unique_lock<std::mutex>{device->FilterLock}; + if(values[2] && (filter=LookupFilter(device, static_cast<ALuint>(values[2]))) == nullptr) + SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid filter ID %u", values[2]); + + if(!filter) + { + /* Disable filter */ + auto &send = Source->Send[static_cast<ALuint>(values[1])]; + send.Gain = 1.0f; + send.GainHF = 1.0f; + send.HFReference = LOWPASSFREQREF; + send.GainLF = 1.0f; + send.LFReference = HIGHPASSFREQREF; + } + else + { + auto &send = Source->Send[static_cast<ALuint>(values[1])]; + send.Gain = filter->Gain; + send.GainHF = filter->GainHF; + send.HFReference = filter->HFReference; + send.GainLF = filter->GainLF; + send.LFReference = filter->LFReference; + } + filtlock.unlock(); + + if(slot != Source->Send[static_cast<ALuint>(values[1])].Slot && IsPlayingOrPaused(Source)) + { + /* Add refcount on the new slot, and release the previous slot */ + if(slot) IncrementRef(slot->ref); + if(auto *slot = Source->Send[static_cast<ALuint>(values[1])].Slot) + DecrementRef(slot->ref); + Source->Send[static_cast<ALuint>(values[1])].Slot = slot; + + /* We must force an update if the auxiliary slot changed on an + * active source, in case the slot is about to be deleted. + */ + ALvoice *voice{GetSourceVoice(Source, Context)}; + if(voice) UpdateSourceProps(Source, voice, Context); + else Source->PropsClean.clear(std::memory_order_release); + } + else + { + if(slot) IncrementRef(slot->ref); + if(auto *slot = Source->Send[static_cast<ALuint>(values[1])].Slot) + DecrementRef(slot->ref); + Source->Send[static_cast<ALuint>(values[1])].Slot = slot; + UpdateSourceProps(Source, Context); + } + return true; + + + /* 1x float */ + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_SOURCE_RADIUS: + CHECKSIZE(values, 1); + fvals[0] = static_cast<ALfloat>(values[0]); + return SetSourcefv(Source, Context, prop, {fvals, 1u}); + + /* 3x float */ + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + CHECKSIZE(values, 3); + fvals[0] = static_cast<ALfloat>(values[0]); + fvals[1] = static_cast<ALfloat>(values[1]); + fvals[2] = static_cast<ALfloat>(values[2]); + return SetSourcefv(Source, Context, prop, {fvals, 3u}); + + /* 6x float */ + case AL_ORIENTATION: + CHECKSIZE(values, 6); + fvals[0] = static_cast<ALfloat>(values[0]); + fvals[1] = static_cast<ALfloat>(values[1]); + fvals[2] = static_cast<ALfloat>(values[2]); + fvals[3] = static_cast<ALfloat>(values[3]); + fvals[4] = static_cast<ALfloat>(values[4]); + fvals[5] = static_cast<ALfloat>(values[5]); + return SetSourcefv(Source, Context, prop, {fvals, 6u}); + + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_CLOCK_SOFT: + case AL_SAMPLE_OFFSET_CLOCK_SOFT: + case AL_STEREO_ANGLES: + break; } ERR("Unexpected property: 0x%04x\n", prop); @@ -1428,101 +1430,100 @@ bool SetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, const switch(prop) { - case AL_SOURCE_TYPE: - case AL_BUFFERS_QUEUED: - case AL_BUFFERS_PROCESSED: - case AL_SOURCE_STATE: - case AL_SAMPLE_OFFSET_LATENCY_SOFT: - case AL_SAMPLE_OFFSET_CLOCK_SOFT: - /* Query only */ - SETERR_RETURN(Context, AL_INVALID_OPERATION, false, - "Setting read-only source property 0x%04x", prop); - - /* 1x int */ - case AL_SOURCE_RELATIVE: - case AL_LOOPING: - case AL_SEC_OFFSET: - case AL_SAMPLE_OFFSET: - case AL_BYTE_OFFSET: - case AL_DIRECT_FILTER_GAINHF_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: - case AL_DIRECT_CHANNELS_SOFT: - case AL_DISTANCE_MODEL: - case AL_SOURCE_RESAMPLER_SOFT: - case AL_SOURCE_SPATIALIZE_SOFT: - CHECKSIZE(values, 1); - CHECKVAL(values[0] <= INT_MAX && values[0] >= INT_MIN); - - ivals[0] = static_cast<ALint>(values[0]); - return SetSourceiv(Source, Context, prop, {ivals, 1u}); - - /* 1x uint */ - case AL_BUFFER: - case AL_DIRECT_FILTER: - CHECKSIZE(values, 1); - CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0); - - ivals[0] = static_cast<ALuint>(values[0]); - return SetSourceiv(Source, Context, prop, {ivals, 1u}); - - /* 3x uint */ - case AL_AUXILIARY_SEND_FILTER: - CHECKSIZE(values, 3); - CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 && - values[1] <= UINT_MAX && values[1] >= 0 && - values[2] <= UINT_MAX && values[2] >= 0); - - ivals[0] = static_cast<ALuint>(values[0]); - ivals[1] = static_cast<ALuint>(values[1]); - ivals[2] = static_cast<ALuint>(values[2]); - return SetSourceiv(Source, Context, prop, {ivals, 3u}); - - /* 1x float */ - case AL_CONE_INNER_ANGLE: - case AL_CONE_OUTER_ANGLE: - case AL_PITCH: - case AL_GAIN: - case AL_MIN_GAIN: - case AL_MAX_GAIN: - case AL_REFERENCE_DISTANCE: - case AL_ROLLOFF_FACTOR: - case AL_CONE_OUTER_GAIN: - case AL_MAX_DISTANCE: - case AL_DOPPLER_FACTOR: - case AL_CONE_OUTER_GAINHF: - case AL_AIR_ABSORPTION_FACTOR: - case AL_ROOM_ROLLOFF_FACTOR: - case AL_SOURCE_RADIUS: - CHECKSIZE(values, 1); - fvals[0] = static_cast<ALfloat>(values[0]); - return SetSourcefv(Source, Context, prop, {fvals, 1u}); - - /* 3x float */ - case AL_POSITION: - case AL_VELOCITY: - case AL_DIRECTION: - CHECKSIZE(values, 3); - fvals[0] = static_cast<ALfloat>(values[0]); - fvals[1] = static_cast<ALfloat>(values[1]); - fvals[2] = static_cast<ALfloat>(values[2]); - return SetSourcefv(Source, Context, prop, {fvals, 3u}); - - /* 6x float */ - case AL_ORIENTATION: - CHECKSIZE(values, 6); - fvals[0] = static_cast<ALfloat>(values[0]); - fvals[1] = static_cast<ALfloat>(values[1]); - fvals[2] = static_cast<ALfloat>(values[2]); - fvals[3] = static_cast<ALfloat>(values[3]); - fvals[4] = static_cast<ALfloat>(values[4]); - fvals[5] = static_cast<ALfloat>(values[5]); - return SetSourcefv(Source, Context, prop, {fvals, 6u}); - - case AL_SEC_OFFSET_LATENCY_SOFT: - case AL_SEC_OFFSET_CLOCK_SOFT: - case AL_STEREO_ANGLES: - break; + case AL_SOURCE_TYPE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_STATE: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SAMPLE_OFFSET_CLOCK_SOFT: + /* Query only */ + SETERR_RETURN(Context, AL_INVALID_OPERATION, false, + "Setting read-only source property 0x%04x", prop); + + /* 1x int */ + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RESAMPLER_SOFT: + case AL_SOURCE_SPATIALIZE_SOFT: + CHECKSIZE(values, 1); + CHECKVAL(values[0] <= INT_MAX && values[0] >= INT_MIN); + + ivals[0] = static_cast<ALint>(values[0]); + return SetSourceiv(Source, Context, prop, {ivals, 1u}); + + /* 1x uint */ + case AL_BUFFER: + case AL_DIRECT_FILTER: + CHECKSIZE(values, 1); + CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0); + + ivals[0] = static_cast<ALint>(values[0]); + return SetSourceiv(Source, Context, prop, {ivals, 1u}); + + /* 3x uint */ + case AL_AUXILIARY_SEND_FILTER: + CHECKSIZE(values, 3); + CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 && values[1] <= UINT_MAX && values[1] >= 0 + && values[2] <= UINT_MAX && values[2] >= 0); + + ivals[0] = static_cast<ALint>(values[0]); + ivals[1] = static_cast<ALint>(values[1]); + ivals[2] = static_cast<ALint>(values[2]); + return SetSourceiv(Source, Context, prop, {ivals, 3u}); + + /* 1x float */ + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_SOURCE_RADIUS: + CHECKSIZE(values, 1); + fvals[0] = static_cast<ALfloat>(values[0]); + return SetSourcefv(Source, Context, prop, {fvals, 1u}); + + /* 3x float */ + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + CHECKSIZE(values, 3); + fvals[0] = static_cast<ALfloat>(values[0]); + fvals[1] = static_cast<ALfloat>(values[1]); + fvals[2] = static_cast<ALfloat>(values[2]); + return SetSourcefv(Source, Context, prop, {fvals, 3u}); + + /* 6x float */ + case AL_ORIENTATION: + CHECKSIZE(values, 6); + fvals[0] = static_cast<ALfloat>(values[0]); + fvals[1] = static_cast<ALfloat>(values[1]); + fvals[2] = static_cast<ALfloat>(values[2]); + fvals[3] = static_cast<ALfloat>(values[3]); + fvals[4] = static_cast<ALfloat>(values[4]); + fvals[5] = static_cast<ALfloat>(values[5]); + return SetSourcefv(Source, Context, prop, {fvals, 6u}); + + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_CLOCK_SOFT: + case AL_STEREO_ANGLES: + break; } ERR("Unexpected property: 0x%04x\n", prop); @@ -1541,185 +1542,185 @@ bool GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a { ALCdevice *device{Context->mDevice.get()}; ClockLatency clocktime; - std::chrono::nanoseconds srcclock; + nanoseconds srcclock; ALint ivals[MaxValues]; bool err; switch(prop) { - case AL_GAIN: - CHECKSIZE(values, 1); - values[0] = Source->Gain; - return true; - - case AL_PITCH: - CHECKSIZE(values, 1); - values[0] = Source->Pitch; - return true; - - case AL_MAX_DISTANCE: - CHECKSIZE(values, 1); - values[0] = Source->MaxDistance; - return true; - - case AL_ROLLOFF_FACTOR: - CHECKSIZE(values, 1); - values[0] = Source->RolloffFactor; - return true; - - case AL_REFERENCE_DISTANCE: - CHECKSIZE(values, 1); - values[0] = Source->RefDistance; - return true; - - case AL_CONE_INNER_ANGLE: - CHECKSIZE(values, 1); - values[0] = Source->InnerAngle; - return true; - - case AL_CONE_OUTER_ANGLE: - CHECKSIZE(values, 1); - values[0] = Source->OuterAngle; - return true; - - case AL_MIN_GAIN: - CHECKSIZE(values, 1); - values[0] = Source->MinGain; - return true; - - case AL_MAX_GAIN: - CHECKSIZE(values, 1); - values[0] = Source->MaxGain; - return true; - - case AL_CONE_OUTER_GAIN: - CHECKSIZE(values, 1); - values[0] = Source->OuterGain; - return true; - - case AL_SEC_OFFSET: - case AL_SAMPLE_OFFSET: - case AL_BYTE_OFFSET: - CHECKSIZE(values, 1); - values[0] = GetSourceOffset(Source, prop, Context); - return true; - - case AL_CONE_OUTER_GAINHF: - CHECKSIZE(values, 1); - values[0] = Source->OuterGainHF; - return true; - - case AL_AIR_ABSORPTION_FACTOR: - CHECKSIZE(values, 1); - values[0] = Source->AirAbsorptionFactor; - return true; - - case AL_ROOM_ROLLOFF_FACTOR: - CHECKSIZE(values, 1); - values[0] = Source->RoomRolloffFactor; - return true; - - case AL_DOPPLER_FACTOR: - CHECKSIZE(values, 1); - values[0] = Source->DopplerFactor; - return true; - - case AL_SOURCE_RADIUS: - CHECKSIZE(values, 1); - values[0] = Source->Radius; - return true; - - case AL_STEREO_ANGLES: - CHECKSIZE(values, 2); - values[0] = Source->StereoPan[0]; - values[1] = Source->StereoPan[1]; - return true; - - case AL_SEC_OFFSET_LATENCY_SOFT: - CHECKSIZE(values, 2); - /* Get the source offset with the clock time first. Then get the - * clock time with the device latency. Order is important. + case AL_GAIN: + CHECKSIZE(values, 1); + values[0] = Source->Gain; + return true; + + case AL_PITCH: + CHECKSIZE(values, 1); + values[0] = Source->Pitch; + return true; + + case AL_MAX_DISTANCE: + CHECKSIZE(values, 1); + values[0] = Source->MaxDistance; + return true; + + case AL_ROLLOFF_FACTOR: + CHECKSIZE(values, 1); + values[0] = Source->RolloffFactor; + return true; + + case AL_REFERENCE_DISTANCE: + CHECKSIZE(values, 1); + values[0] = Source->RefDistance; + return true; + + case AL_CONE_INNER_ANGLE: + CHECKSIZE(values, 1); + values[0] = Source->InnerAngle; + return true; + + case AL_CONE_OUTER_ANGLE: + CHECKSIZE(values, 1); + values[0] = Source->OuterAngle; + return true; + + case AL_MIN_GAIN: + CHECKSIZE(values, 1); + values[0] = Source->MinGain; + return true; + + case AL_MAX_GAIN: + CHECKSIZE(values, 1); + values[0] = Source->MaxGain; + return true; + + case AL_CONE_OUTER_GAIN: + CHECKSIZE(values, 1); + values[0] = Source->OuterGain; + return true; + + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + CHECKSIZE(values, 1); + values[0] = GetSourceOffset(Source, prop, Context); + return true; + + case AL_CONE_OUTER_GAINHF: + CHECKSIZE(values, 1); + values[0] = Source->OuterGainHF; + return true; + + case AL_AIR_ABSORPTION_FACTOR: + CHECKSIZE(values, 1); + values[0] = Source->AirAbsorptionFactor; + return true; + + case AL_ROOM_ROLLOFF_FACTOR: + CHECKSIZE(values, 1); + values[0] = Source->RoomRolloffFactor; + return true; + + case AL_DOPPLER_FACTOR: + CHECKSIZE(values, 1); + values[0] = Source->DopplerFactor; + return true; + + case AL_SOURCE_RADIUS: + CHECKSIZE(values, 1); + values[0] = Source->Radius; + return true; + + case AL_STEREO_ANGLES: + CHECKSIZE(values, 2); + values[0] = Source->StereoPan[0]; + values[1] = Source->StereoPan[1]; + return true; + + case AL_SEC_OFFSET_LATENCY_SOFT: + CHECKSIZE(values, 2); + /* Get the source offset with the clock time first. Then get the clock + * time with the device latency. Order is important. + */ + values[0] = GetSourceSecOffset(Source, Context, &srcclock); + { + std::lock_guard<std::mutex> _{device->StateLock}; + clocktime = GetClockLatency(device); + } + if(srcclock == clocktime.ClockTime) + values[1] = static_cast<ALdouble>(clocktime.Latency.count()) / 1000000000.0; + else + { + /* If the clock time incremented, reduce the latency by that much + * since it's that much closer to the source offset it got earlier. */ - values[0] = GetSourceSecOffset(Source, Context, &srcclock); - { std::lock_guard<std::mutex> _{device->StateLock}; - clocktime = GetClockLatency(device); - } - if(srcclock == clocktime.ClockTime) - values[1] = static_cast<ALdouble>(clocktime.Latency.count()) / 1000000000.0; - else - { - /* If the clock time incremented, reduce the latency by that - * much since it's that much closer to the source offset it got - * earlier. - */ - std::chrono::nanoseconds diff = clocktime.ClockTime - srcclock; - values[1] = static_cast<ALdouble>((clocktime.Latency - std::min(clocktime.Latency, diff)).count()) / - 1000000000.0; - } - return true; - - case AL_SEC_OFFSET_CLOCK_SOFT: - CHECKSIZE(values, 2); - values[0] = GetSourceSecOffset(Source, Context, &srcclock); - values[1] = srcclock.count() / 1000000000.0; - return true; - - case AL_POSITION: - CHECKSIZE(values, 3); - values[0] = Source->Position[0]; - values[1] = Source->Position[1]; - values[2] = Source->Position[2]; - return true; - - case AL_VELOCITY: - CHECKSIZE(values, 3); - values[0] = Source->Velocity[0]; - values[1] = Source->Velocity[1]; - values[2] = Source->Velocity[2]; - return true; - - case AL_DIRECTION: - CHECKSIZE(values, 3); - values[0] = Source->Direction[0]; - values[1] = Source->Direction[1]; - values[2] = Source->Direction[2]; - return true; - - case AL_ORIENTATION: - CHECKSIZE(values, 6); - values[0] = Source->OrientAt[0]; - values[1] = Source->OrientAt[1]; - values[2] = Source->OrientAt[2]; - values[3] = Source->OrientUp[0]; - values[4] = Source->OrientUp[1]; - values[5] = Source->OrientUp[2]; - return true; - - /* 1x int */ - case AL_SOURCE_RELATIVE: - case AL_LOOPING: - case AL_SOURCE_STATE: - case AL_BUFFERS_QUEUED: - case AL_BUFFERS_PROCESSED: - case AL_SOURCE_TYPE: - case AL_DIRECT_FILTER_GAINHF_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: - case AL_DIRECT_CHANNELS_SOFT: - case AL_DISTANCE_MODEL: - case AL_SOURCE_RESAMPLER_SOFT: - case AL_SOURCE_SPATIALIZE_SOFT: - CHECKSIZE(values, 1); - if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false) - values[0] = static_cast<ALdouble>(ivals[0]); - return err; - - case AL_BUFFER: - case AL_DIRECT_FILTER: - case AL_AUXILIARY_SEND_FILTER: - case AL_SAMPLE_OFFSET_LATENCY_SOFT: - case AL_SAMPLE_OFFSET_CLOCK_SOFT: - break; + const nanoseconds diff{clocktime.ClockTime - srcclock}; + const nanoseconds latency{clocktime.Latency - std::min(clocktime.Latency, diff)}; + values[1] = static_cast<ALdouble>(latency.count()) / 1000000000.0; + } + return true; + + case AL_SEC_OFFSET_CLOCK_SOFT: + CHECKSIZE(values, 2); + values[0] = GetSourceSecOffset(Source, Context, &srcclock); + values[1] = srcclock.count() / 1000000000.0; + return true; + + case AL_POSITION: + CHECKSIZE(values, 3); + values[0] = Source->Position[0]; + values[1] = Source->Position[1]; + values[2] = Source->Position[2]; + return true; + + case AL_VELOCITY: + CHECKSIZE(values, 3); + values[0] = Source->Velocity[0]; + values[1] = Source->Velocity[1]; + values[2] = Source->Velocity[2]; + return true; + + case AL_DIRECTION: + CHECKSIZE(values, 3); + values[0] = Source->Direction[0]; + values[1] = Source->Direction[1]; + values[2] = Source->Direction[2]; + return true; + + case AL_ORIENTATION: + CHECKSIZE(values, 6); + values[0] = Source->OrientAt[0]; + values[1] = Source->OrientAt[1]; + values[2] = Source->OrientAt[2]; + values[3] = Source->OrientUp[0]; + values[4] = Source->OrientUp[1]; + values[5] = Source->OrientUp[2]; + return true; + + /* 1x int */ + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RESAMPLER_SOFT: + case AL_SOURCE_SPATIALIZE_SOFT: + CHECKSIZE(values, 1); + if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false) + values[0] = static_cast<ALdouble>(ivals[0]); + return err; + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SAMPLE_OFFSET_CLOCK_SOFT: + break; } ERR("Unexpected property: 0x%04x\n", prop); @@ -1735,174 +1736,176 @@ bool GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a switch(prop) { - case AL_SOURCE_RELATIVE: - CHECKSIZE(values, 1); - values[0] = Source->HeadRelative; - return true; - - case AL_LOOPING: - CHECKSIZE(values, 1); - values[0] = Source->Looping; - return true; - - case AL_BUFFER: - CHECKSIZE(values, 1); - BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : nullptr; - values[0] = (BufferList && BufferList->mBuffer) ? BufferList->mBuffer->id : 0; - return true; - - case AL_SOURCE_STATE: - CHECKSIZE(values, 1); - values[0] = GetSourceState(Source, GetSourceVoice(Source, Context)); - return true; - - case AL_BUFFERS_QUEUED: - CHECKSIZE(values, 1); - if(!(BufferList=Source->queue)) - values[0] = 0; - else - { - ALsizei count{0}; - do { - ++count; - BufferList = BufferList->mNext.load(std::memory_order_relaxed); - } while(BufferList != nullptr); - values[0] = count; - } - return true; + case AL_SOURCE_RELATIVE: + CHECKSIZE(values, 1); + values[0] = Source->HeadRelative; + return true; + + case AL_LOOPING: + CHECKSIZE(values, 1); + values[0] = Source->Looping; + return true; + + case AL_BUFFER: + CHECKSIZE(values, 1); + BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : nullptr; + values[0] = (BufferList && BufferList->mBuffer) ? + static_cast<ALint>(BufferList->mBuffer->id) : 0; + return true; + + case AL_SOURCE_STATE: + CHECKSIZE(values, 1); + values[0] = GetSourceState(Source, GetSourceVoice(Source, Context)); + return true; + + case AL_BUFFERS_QUEUED: + CHECKSIZE(values, 1); + if(!(BufferList=Source->queue)) + values[0] = 0; + else + { + ALsizei count{0}; + do { + ++count; + BufferList = BufferList->mNext.load(std::memory_order_relaxed); + } while(BufferList != nullptr); + values[0] = count; + } + return true; - case AL_BUFFERS_PROCESSED: - CHECKSIZE(values, 1); - if(Source->Looping || Source->SourceType != AL_STREAMING) - { - /* Buffers on a looping source are in a perpetual state of - * PENDING, so don't report any as PROCESSED */ - values[0] = 0; - } - else - { - const ALbufferlistitem *BufferList{Source->queue}; - const ALbufferlistitem *Current{nullptr}; - ALsizei played{0}; - - ALvoice *voice{GetSourceVoice(Source, Context)}; - if(voice != nullptr) - Current = voice->mCurrentBuffer.load(std::memory_order_relaxed); - else if(Source->state == AL_INITIAL) - Current = BufferList; - - while(BufferList && BufferList != Current) - { - ++played; - BufferList = BufferList->mNext.load(std::memory_order_relaxed); - } - values[0] = played; - } - return true; - - case AL_SOURCE_TYPE: - CHECKSIZE(values, 1); - values[0] = Source->SourceType; - return true; - - case AL_DIRECT_FILTER_GAINHF_AUTO: - CHECKSIZE(values, 1); - values[0] = Source->DryGainHFAuto; - return true; - - case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: - CHECKSIZE(values, 1); - values[0] = Source->WetGainAuto; - return true; - - case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: - CHECKSIZE(values, 1); - values[0] = Source->WetGainHFAuto; - return true; - - case AL_DIRECT_CHANNELS_SOFT: - CHECKSIZE(values, 1); - values[0] = Source->DirectChannels; - return true; - - case AL_DISTANCE_MODEL: - CHECKSIZE(values, 1); - values[0] = static_cast<int>(Source->mDistanceModel); - return true; - - case AL_SOURCE_RESAMPLER_SOFT: - CHECKSIZE(values, 1); - values[0] = Source->mResampler; - return true; - - case AL_SOURCE_SPATIALIZE_SOFT: - CHECKSIZE(values, 1); - values[0] = Source->mSpatialize; - return true; - - /* 1x float/double */ - case AL_CONE_INNER_ANGLE: - case AL_CONE_OUTER_ANGLE: - case AL_PITCH: - case AL_GAIN: - case AL_MIN_GAIN: - case AL_MAX_GAIN: - case AL_REFERENCE_DISTANCE: - case AL_ROLLOFF_FACTOR: - case AL_CONE_OUTER_GAIN: - case AL_MAX_DISTANCE: - case AL_SEC_OFFSET: - case AL_SAMPLE_OFFSET: - case AL_BYTE_OFFSET: - case AL_DOPPLER_FACTOR: - case AL_AIR_ABSORPTION_FACTOR: - case AL_ROOM_ROLLOFF_FACTOR: - case AL_CONE_OUTER_GAINHF: - case AL_SOURCE_RADIUS: - CHECKSIZE(values, 1); - if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false) - values[0] = static_cast<ALint>(dvals[0]); - return err; - - /* 3x float/double */ - case AL_POSITION: - case AL_VELOCITY: - case AL_DIRECTION: - CHECKSIZE(values, 3); - if((err=GetSourcedv(Source, Context, prop, {dvals, 3u})) != false) - { - values[0] = static_cast<ALint>(dvals[0]); - values[1] = static_cast<ALint>(dvals[1]); - values[2] = static_cast<ALint>(dvals[2]); - } - return err; + case AL_BUFFERS_PROCESSED: + CHECKSIZE(values, 1); + if(Source->Looping || Source->SourceType != AL_STREAMING) + { + /* Buffers on a looping source are in a perpetual state of PENDING, + * so don't report any as PROCESSED + */ + values[0] = 0; + } + else + { + const ALbufferlistitem *BufferList{Source->queue}; + const ALbufferlistitem *Current{nullptr}; + ALsizei played{0}; + + ALvoice *voice{GetSourceVoice(Source, Context)}; + if(voice != nullptr) + Current = voice->mCurrentBuffer.load(std::memory_order_relaxed); + else if(Source->state == AL_INITIAL) + Current = BufferList; - /* 6x float/double */ - case AL_ORIENTATION: - CHECKSIZE(values, 6); - if((err=GetSourcedv(Source, Context, prop, {dvals, 6u})) != false) + while(BufferList && BufferList != Current) { - values[0] = static_cast<ALint>(dvals[0]); - values[1] = static_cast<ALint>(dvals[1]); - values[2] = static_cast<ALint>(dvals[2]); - values[3] = static_cast<ALint>(dvals[3]); - values[4] = static_cast<ALint>(dvals[4]); - values[5] = static_cast<ALint>(dvals[5]); + ++played; + BufferList = BufferList->mNext.load(std::memory_order_relaxed); } - return err; - - case AL_SAMPLE_OFFSET_LATENCY_SOFT: - case AL_SAMPLE_OFFSET_CLOCK_SOFT: - break; /* i64 only */ - case AL_SEC_OFFSET_LATENCY_SOFT: - case AL_SEC_OFFSET_CLOCK_SOFT: - break; /* Double only */ - case AL_STEREO_ANGLES: - break; /* Float/double only */ - - case AL_DIRECT_FILTER: - case AL_AUXILIARY_SEND_FILTER: - break; /* ??? */ + values[0] = played; + } + return true; + + case AL_SOURCE_TYPE: + CHECKSIZE(values, 1); + values[0] = Source->SourceType; + return true; + + case AL_DIRECT_FILTER_GAINHF_AUTO: + CHECKSIZE(values, 1); + values[0] = Source->DryGainHFAuto; + return true; + + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + CHECKSIZE(values, 1); + values[0] = Source->WetGainAuto; + return true; + + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + CHECKSIZE(values, 1); + values[0] = Source->WetGainHFAuto; + return true; + + case AL_DIRECT_CHANNELS_SOFT: + CHECKSIZE(values, 1); + values[0] = Source->DirectChannels; + return true; + + case AL_DISTANCE_MODEL: + CHECKSIZE(values, 1); + values[0] = static_cast<int>(Source->mDistanceModel); + return true; + + case AL_SOURCE_RESAMPLER_SOFT: + CHECKSIZE(values, 1); + values[0] = Source->mResampler; + return true; + + case AL_SOURCE_SPATIALIZE_SOFT: + CHECKSIZE(values, 1); + values[0] = Source->mSpatialize; + return true; + + /* 1x float/double */ + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_DOPPLER_FACTOR: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_SOURCE_RADIUS: + CHECKSIZE(values, 1); + if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false) + values[0] = static_cast<ALint>(dvals[0]); + return err; + + /* 3x float/double */ + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + CHECKSIZE(values, 3); + if((err=GetSourcedv(Source, Context, prop, {dvals, 3u})) != false) + { + values[0] = static_cast<ALint>(dvals[0]); + values[1] = static_cast<ALint>(dvals[1]); + values[2] = static_cast<ALint>(dvals[2]); + } + return err; + + /* 6x float/double */ + case AL_ORIENTATION: + CHECKSIZE(values, 6); + if((err=GetSourcedv(Source, Context, prop, {dvals, 6u})) != false) + { + values[0] = static_cast<ALint>(dvals[0]); + values[1] = static_cast<ALint>(dvals[1]); + values[2] = static_cast<ALint>(dvals[2]); + values[3] = static_cast<ALint>(dvals[3]); + values[4] = static_cast<ALint>(dvals[4]); + values[5] = static_cast<ALint>(dvals[5]); + } + return err; + + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SAMPLE_OFFSET_CLOCK_SOFT: + break; /* i64 only */ + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_CLOCK_SOFT: + break; /* Double only */ + case AL_STEREO_ANGLES: + break; /* Float/double only */ + + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + break; /* ??? */ } ERR("Unexpected property: 0x%04x\n", prop); @@ -1914,135 +1917,135 @@ bool GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, const { ALCdevice *device = Context->mDevice.get(); ClockLatency clocktime; - std::chrono::nanoseconds srcclock; + nanoseconds srcclock; ALdouble dvals[MaxValues]; ALint ivals[MaxValues]; bool err; switch(prop) { - case AL_SAMPLE_OFFSET_LATENCY_SOFT: - CHECKSIZE(values, 2); - /* Get the source offset with the clock time first. Then get the - * clock time with the device latency. Order is important. + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + CHECKSIZE(values, 2); + /* Get the source offset with the clock time first. Then get the clock + * time with the device latency. Order is important. + */ + values[0] = GetSourceSampleOffset(Source, Context, &srcclock); + { + std::lock_guard<std::mutex> _{device->StateLock}; + clocktime = GetClockLatency(device); + } + if(srcclock == clocktime.ClockTime) + values[1] = clocktime.Latency.count(); + else + { + /* If the clock time incremented, reduce the latency by that much + * since it's that much closer to the source offset it got earlier. */ - values[0] = GetSourceSampleOffset(Source, Context, &srcclock); - { std::lock_guard<std::mutex> _{device->StateLock}; - clocktime = GetClockLatency(device); - } - if(srcclock == clocktime.ClockTime) - values[1] = clocktime.Latency.count(); - else - { - /* If the clock time incremented, reduce the latency by that - * much since it's that much closer to the source offset it got - * earlier. - */ - auto diff = clocktime.ClockTime - srcclock; - values[1] = (clocktime.Latency - std::min(clocktime.Latency, diff)).count(); - } - return true; - - case AL_SAMPLE_OFFSET_CLOCK_SOFT: - CHECKSIZE(values, 2); - values[0] = GetSourceSampleOffset(Source, Context, &srcclock); - values[1] = srcclock.count(); - return true; - - /* 1x float/double */ - case AL_CONE_INNER_ANGLE: - case AL_CONE_OUTER_ANGLE: - case AL_PITCH: - case AL_GAIN: - case AL_MIN_GAIN: - case AL_MAX_GAIN: - case AL_REFERENCE_DISTANCE: - case AL_ROLLOFF_FACTOR: - case AL_CONE_OUTER_GAIN: - case AL_MAX_DISTANCE: - case AL_SEC_OFFSET: - case AL_SAMPLE_OFFSET: - case AL_BYTE_OFFSET: - case AL_DOPPLER_FACTOR: - case AL_AIR_ABSORPTION_FACTOR: - case AL_ROOM_ROLLOFF_FACTOR: - case AL_CONE_OUTER_GAINHF: - case AL_SOURCE_RADIUS: - CHECKSIZE(values, 1); - if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false) - values[0] = static_cast<int64_t>(dvals[0]); - return err; - - /* 3x float/double */ - case AL_POSITION: - case AL_VELOCITY: - case AL_DIRECTION: - CHECKSIZE(values, 3); - if((err=GetSourcedv(Source, Context, prop, {dvals, 3u})) != false) - { - values[0] = static_cast<int64_t>(dvals[0]); - values[1] = static_cast<int64_t>(dvals[1]); - values[2] = static_cast<int64_t>(dvals[2]); - } - return err; + const nanoseconds diff{clocktime.ClockTime - srcclock}; + values[1] = nanoseconds{clocktime.Latency - std::min(clocktime.Latency, diff)}.count(); + } + return true; + + case AL_SAMPLE_OFFSET_CLOCK_SOFT: + CHECKSIZE(values, 2); + values[0] = GetSourceSampleOffset(Source, Context, &srcclock); + values[1] = srcclock.count(); + return true; + + /* 1x float/double */ + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_DOPPLER_FACTOR: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_SOURCE_RADIUS: + CHECKSIZE(values, 1); + if((err=GetSourcedv(Source, Context, prop, {dvals, 1u})) != false) + values[0] = static_cast<int64_t>(dvals[0]); + return err; + + /* 3x float/double */ + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + CHECKSIZE(values, 3); + if((err=GetSourcedv(Source, Context, prop, {dvals, 3u})) != false) + { + values[0] = static_cast<int64_t>(dvals[0]); + values[1] = static_cast<int64_t>(dvals[1]); + values[2] = static_cast<int64_t>(dvals[2]); + } + return err; - /* 6x float/double */ - case AL_ORIENTATION: - CHECKSIZE(values, 6); - if((err=GetSourcedv(Source, Context, prop, {dvals, 6u})) != false) - { - values[0] = static_cast<int64_t>(dvals[0]); - values[1] = static_cast<int64_t>(dvals[1]); - values[2] = static_cast<int64_t>(dvals[2]); - values[3] = static_cast<int64_t>(dvals[3]); - values[4] = static_cast<int64_t>(dvals[4]); - values[5] = static_cast<int64_t>(dvals[5]); - } - return err; - - /* 1x int */ - case AL_SOURCE_RELATIVE: - case AL_LOOPING: - case AL_SOURCE_STATE: - case AL_BUFFERS_QUEUED: - case AL_BUFFERS_PROCESSED: - case AL_SOURCE_TYPE: - case AL_DIRECT_FILTER_GAINHF_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: - case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: - case AL_DIRECT_CHANNELS_SOFT: - case AL_DISTANCE_MODEL: - case AL_SOURCE_RESAMPLER_SOFT: - case AL_SOURCE_SPATIALIZE_SOFT: - CHECKSIZE(values, 1); - if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false) - values[0] = ivals[0]; - return err; - - /* 1x uint */ - case AL_BUFFER: - case AL_DIRECT_FILTER: - CHECKSIZE(values, 1); - if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false) - values[0] = static_cast<ALuint>(ivals[0]); - return err; - - /* 3x uint */ - case AL_AUXILIARY_SEND_FILTER: - CHECKSIZE(values, 3); - if((err=GetSourceiv(Source, Context, prop, {ivals, 3u})) != false) - { - values[0] = static_cast<ALuint>(ivals[0]); - values[1] = static_cast<ALuint>(ivals[1]); - values[2] = static_cast<ALuint>(ivals[2]); - } - return err; + /* 6x float/double */ + case AL_ORIENTATION: + CHECKSIZE(values, 6); + if((err=GetSourcedv(Source, Context, prop, {dvals, 6u})) != false) + { + values[0] = static_cast<int64_t>(dvals[0]); + values[1] = static_cast<int64_t>(dvals[1]); + values[2] = static_cast<int64_t>(dvals[2]); + values[3] = static_cast<int64_t>(dvals[3]); + values[4] = static_cast<int64_t>(dvals[4]); + values[5] = static_cast<int64_t>(dvals[5]); + } + return err; + + /* 1x int */ + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_DIRECT_FILTER_GAINHF_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + case AL_DIRECT_CHANNELS_SOFT: + case AL_DISTANCE_MODEL: + case AL_SOURCE_RESAMPLER_SOFT: + case AL_SOURCE_SPATIALIZE_SOFT: + CHECKSIZE(values, 1); + if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false) + values[0] = ivals[0]; + return err; + + /* 1x uint */ + case AL_BUFFER: + case AL_DIRECT_FILTER: + CHECKSIZE(values, 1); + if((err=GetSourceiv(Source, Context, prop, {ivals, 1u})) != false) + values[0] = static_cast<ALuint>(ivals[0]); + return err; + + /* 3x uint */ + case AL_AUXILIARY_SEND_FILTER: + CHECKSIZE(values, 3); + if((err=GetSourceiv(Source, Context, prop, {ivals, 3u})) != false) + { + values[0] = static_cast<ALuint>(ivals[0]); + values[1] = static_cast<ALuint>(ivals[1]); + values[2] = static_cast<ALuint>(ivals[2]); + } + return err; - case AL_SEC_OFFSET_LATENCY_SOFT: - case AL_SEC_OFFSET_CLOCK_SOFT: - break; /* Double only */ - case AL_STEREO_ANGLES: - break; /* Float/double only */ + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_CLOCK_SOFT: + break; /* Double only */ + case AL_STEREO_ANGLES: + break; /* Float/double only */ } ERR("Unexpected property: 0x%04x\n", prop); @@ -2060,28 +2063,36 @@ START_API_FUNC if UNLIKELY(n < 0) context->setError(AL_INVALID_VALUE, "Generating %d sources", n); - else if(n == 1) + if UNLIKELY(n <= 0) return; + + std::unique_lock<std::mutex> srclock{context->mSourceLock}; + ALCdevice *device{context->mDevice.get()}; + if(static_cast<ALuint>(n) >= device->SourcesMax-context->mNumSources) + { + context->setError(AL_OUT_OF_MEMORY, "Exceeding %u source limit", device->SourcesMax); + return; + } + if(!EnsureSources(context.get(), static_cast<ALuint>(n))) { - ALsource *source = AllocSource(context.get()); - if(source) sources[0] = source->id; + context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d source%s", n, (n==1)?"":"s"); + return; + } + + if(n == 1) + { + ALsource *source{AllocSource(context.get(), device->NumAuxSends)}; + sources[0] = source->id; } else { - al::vector<ALuint> tempids(n); - auto alloc_end = std::find_if_not(tempids.begin(), tempids.end(), - [&context](ALuint &id) -> bool - { - ALsource *source{AllocSource(context.get())}; - if(!source) return false; - id = source->id; - return true; - } - ); - if(alloc_end != tempids.end()) - alDeleteSources(static_cast<ALsizei>(std::distance(tempids.begin(), alloc_end)), - tempids.data()); - else - std::copy(tempids.cbegin(), tempids.cend(), sources); + const ALsizei num_sends{device->NumAuxSends}; + al::vector<ALuint> ids; + ids.reserve(static_cast<ALuint>(n)); + do { + ALsource *source{AllocSource(context.get(), num_sends)}; + ids.emplace_back(source->id); + } while(--n); + std::copy(ids.cbegin(), ids.cend(), sources); } } END_API_FUNC @@ -2098,29 +2109,24 @@ START_API_FUNC std::lock_guard<std::mutex> _{context->mSourceLock}; /* Check that all Sources are valid */ + auto validate_source = [&context](ALuint sid) -> bool + { return LookupSource(context.get(), sid) != nullptr; }; + const ALuint *sources_end = sources + n; - auto invsrc = std::find_if_not(sources, sources_end, - [&context](ALuint sid) -> bool - { - if(!LookupSource(context.get(), sid)) - { - context->setError(AL_INVALID_NAME, "Invalid source ID %u", sid); - return false; - } - return true; - } - ); - if LIKELY(invsrc == sources_end) + auto invsrc = std::find_if_not(sources, sources_end, validate_source); + if UNLIKELY(invsrc != sources_end) { - /* All good. Delete source IDs. */ - std::for_each(sources, sources_end, - [&context](ALuint sid) -> void - { - ALsource *src{LookupSource(context.get(), sid)}; - if(src) FreeSource(context.get(), src); - } - ); + context->setError(AL_INVALID_NAME, "Invalid source ID %u", *invsrc); + return; } + + /* All good. Delete source IDs. */ + auto delete_source = [&context](ALuint sid) -> void + { + ALsource *src{LookupSource(context.get(), sid)}; + if(src) FreeSource(context.get(), src); + }; + std::for_each(sources, sources_end, delete_source); } END_API_FUNC @@ -2637,7 +2643,7 @@ START_API_FUNC ALsource **srchandles{source_storage.data()}; if UNLIKELY(static_cast<ALuint>(n) > source_storage.size()) { - extra_sources.resize(n); + extra_sources.resize(static_cast<ALuint>(n)); srchandles = extra_sources.data(); } @@ -2667,16 +2673,16 @@ START_API_FUNC } /* Count the number of reusable voices. */ - auto count_free_voices = [](const ALsizei count, const ALvoice &voice) noexcept -> ALsizei + auto count_free_voices = [](const ALuint count, const ALvoice &voice) noexcept -> ALuint { - if(voice.mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped && - voice.mSourceID.load(std::memory_order_relaxed) == 0u) + if(voice.mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped + && voice.mSourceID.load(std::memory_order_relaxed) == 0u) return count + 1; return count; }; auto free_voices = std::accumulate(context->mVoices.begin(), context->mVoices.end(), - ALsizei{0}, count_free_voices); - if UNLIKELY(n > free_voices) + ALuint{0}, count_free_voices); + if UNLIKELY(static_cast<ALuint>(n) > free_voices) { /* Increase the number of voices to handle the request. */ const ALuint need_voices{static_cast<ALuint>(n) - free_voices}; @@ -2775,7 +2781,7 @@ START_API_FUNC } ALbuffer *buffer{BufferList->mBuffer}; - voice->mFrequency = buffer->Frequency; + voice->mFrequency = static_cast<ALuint>(buffer->Frequency); voice->mFmtChannels = buffer->mFmtChannels; voice->mNumChannels = ChannelsFromFmt(buffer->mFmtChannels); voice->mSampleSize = BytesFromFmt(buffer->mFmtType); @@ -2791,20 +2797,20 @@ START_API_FUNC /* Don't need to set the VOICE_IS_AMBISONIC flag if the device is * mixing in first order. No HF scaling is necessary to mix it. */ - if((voice->mFmtChannels == FmtBFormat2D || voice->mFmtChannels == FmtBFormat3D) && - device->mAmbiOrder > 1) + if((voice->mFmtChannels == FmtBFormat2D || voice->mFmtChannels == FmtBFormat3D) + && device->mAmbiOrder > 1) { - const int *OrderFromChan; + const ALuint *OrderFromChan; if(voice->mFmtChannels == FmtBFormat2D) { - static constexpr int Order2DFromChan[MAX_AMBI2D_CHANNELS]{ + static constexpr ALuint Order2DFromChan[MAX_AMBI2D_CHANNELS]{ 0, 1,1, 2,2, 3,3 }; OrderFromChan = Order2DFromChan; } else { - static constexpr int Order3DFromChan[MAX_AMBI_CHANNELS]{ + static constexpr ALuint Order3DFromChan[MAX_AMBI_CHANNELS]{ 0, 1,1,1, 2,2,2,2,2, 3,3,3,3,3,3,3, }; OrderFromChan = Order3DFromChan; @@ -2886,7 +2892,7 @@ START_API_FUNC ALsource **srchandles{source_storage.data()}; if UNLIKELY(static_cast<ALuint>(n) > source_storage.size()) { - extra_sources.resize(n); + extra_sources.resize(static_cast<ALuint>(n)); srchandles = extra_sources.data(); } @@ -2941,7 +2947,7 @@ START_API_FUNC ALsource **srchandles{source_storage.data()}; if UNLIKELY(static_cast<ALuint>(n) > source_storage.size()) { - extra_sources.resize(n); + extra_sources.resize(static_cast<ALuint>(n)); srchandles = extra_sources.data(); } @@ -3006,7 +3012,7 @@ START_API_FUNC ALsource **srchandles{source_storage.data()}; if UNLIKELY(static_cast<ALuint>(n) > source_storage.size()) { - extra_sources.resize(n); + extra_sources.resize(static_cast<ALuint>(n)); srchandles = extra_sources.data(); } @@ -3197,8 +3203,7 @@ START_API_FUNC ++i; } - while(nb > 0) - { + do { std::unique_ptr<ALbufferlistitem> head{source->queue}; source->queue = head->mNext.load(std::memory_order_relaxed); @@ -3209,8 +3214,7 @@ START_API_FUNC } else *(buffers++) = 0; - --nb; - } + } while(--nb); } END_API_FUNC @@ -3267,7 +3271,7 @@ ALsource::ALsource(ALsizei num_sends) Direct.HFReference = LOWPASSFREQREF; Direct.GainLF = 1.0f; Direct.LFReference = HIGHPASSFREQREF; - Send.resize(num_sends); + Send.resize(static_cast<ALuint>(num_sends)); for(auto &send : Send) { send.Slot = nullptr; diff --git a/al/source.h b/al/source.h index 05037fd3..e0219a04 100644 --- a/al/source.h +++ b/al/source.h @@ -49,17 +49,17 @@ struct ALsource { std::array<ALfloat,3> Direction; std::array<ALfloat,3> OrientAt; std::array<ALfloat,3> OrientUp; - ALboolean HeadRelative; - ALboolean Looping; + bool HeadRelative; + bool Looping; DistanceModel mDistanceModel; Resampler mResampler; - ALboolean DirectChannels; + bool DirectChannels; SpatializeMode mSpatialize; - ALboolean DryGainHFAuto; - ALboolean WetGainAuto; - ALboolean WetGainHFAuto; - ALfloat OuterGainHF; + bool DryGainHFAuto; + bool WetGainAuto; + bool WetGainHFAuto; + ALfloat OuterGainHF; ALfloat AirAbsorptionFactor; ALfloat RoomRolloffFactor; @@ -98,7 +98,7 @@ struct ALsource { ALenum OffsetType{AL_NONE}; /** Source type (static, streaming, or undetermined) */ - ALint SourceType{AL_UNDETERMINED}; + ALenum SourceType{AL_UNDETERMINED}; /** Source state (initial, playing, paused, or stopped) */ ALenum state{AL_INITIAL}; |