diff options
Diffstat (limited to 'al/source.cpp')
-rw-r--r-- | al/source.cpp | 289 |
1 files changed, 149 insertions, 140 deletions
diff --git a/al/source.cpp b/al/source.cpp index fe5bba40..b3af9428 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -80,7 +80,7 @@ namespace { -using namespace std::placeholders; +using SubListAllocator = typename al::allocator<std::array<ALsource,64>>; using std::chrono::nanoseconds; using seconds_d = std::chrono::duration<double>; @@ -171,7 +171,7 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context ret.LFReference = srcsend.LFReference; return ret; }; - std::transform(source->Send.cbegin(), source->Send.cend(), props->Send, copy_send); + std::transform(source->Send.cbegin(), source->Send.cend(), props->Send.begin(), copy_send); if(!props->Send[0].Slot && context->mDefaultSlot) props->Send[0].Slot = context->mDefaultSlot->mSlot; @@ -202,7 +202,7 @@ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds do { refcount = device->waitForMix(); - *clocktime = GetDeviceClockTime(device); + *clocktime = device->getClockTime(); voice = GetSourceVoice(Source, context); if(voice) { @@ -212,7 +212,7 @@ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds readPos += voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return 0; @@ -242,7 +242,7 @@ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *cl do { refcount = device->waitForMix(); - *clocktime = GetDeviceClockTime(device); + *clocktime = device->getClockTime(); voice = GetSourceVoice(Source, context); if(voice) { @@ -252,7 +252,7 @@ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *cl readPos += voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return 0.0f; @@ -302,7 +302,7 @@ NOINLINE T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) readPosFrac = voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return T{0}; @@ -575,7 +575,7 @@ void SendVoiceChanges(ALCcontext *ctx, VoiceChange *tail) oldhead->mNext.store(tail, std::memory_order_release); const bool connected{device->Connected.load(std::memory_order_acquire)}; - device->waitForMix(); + std::ignore = device->waitForMix(); if(!connected) UNLIKELY { if(ctx->mStopVoicesOnDisconnect.load(std::memory_order_acquire)) @@ -681,7 +681,7 @@ bool SetVoiceOffset(Voice *oldvoice, const VoicePos &vpos, ALsource *source, ALC return true; /* Otherwise, wait for any current mix to finish and check one last time. */ - device->waitForMix(); + std::ignore = device->waitForMix(); if(newvoice->mPlayState.load(std::memory_order_acquire) != Voice::Pending) return true; /* The change-over failed because the old voice stopped before the new @@ -721,21 +721,21 @@ bool EnsureSources(ALCcontext *context, size_t needed) [](size_t cur, const SourceSubList &sublist) noexcept -> size_t { return cur + static_cast<ALuint>(al::popcount(sublist.FreeMask)); })}; - while(needed > count) - { - if(context->mSourceList.size() >= 1<<25) UNLIKELY - return false; - - context->mSourceList.emplace_back(); - auto sublist = context->mSourceList.end() - 1; - sublist->FreeMask = ~0_u64; - sublist->Sources = static_cast<ALsource*>(al_calloc(alignof(ALsource), sizeof(ALsource)*64)); - if(!sublist->Sources) UNLIKELY + try { + while(needed > count) { - context->mSourceList.pop_back(); - return false; + if(context->mSourceList.size() >= 1<<25) UNLIKELY + return false; + + SourceSubList sublist{}; + sublist.FreeMask = ~0_u64; + sublist.Sources = SubListAllocator{}.allocate(1); + context->mSourceList.emplace_back(std::move(sublist)); + count += 64; } - count += 64; + } + catch(...) { + return false; } return true; } @@ -749,7 +749,7 @@ ALsource *AllocSource(ALCcontext *context) auto slidx = static_cast<ALuint>(al::countr_zero(sublist->FreeMask)); ASSUME(slidx < 64); - ALsource *source{al::construct_at(sublist->Sources + slidx)}; + ALsource *source{al::construct_at(al::to_address(sublist->Sources->begin() + slidx))}; /* Add 1 to avoid source ID 0. */ source->id = ((lidx<<6) | slidx) + 1; @@ -797,7 +797,7 @@ inline ALsource *LookupSource(ALCcontext *context, ALuint id) noexcept SourceSubList &sublist{context->mSourceList[lidx]}; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Sources + slidx; + return al::to_address(sublist.Sources->begin() + slidx); } auto LookupBuffer = [](ALCdevice *device, auto id) noexcept -> ALbuffer* @@ -810,7 +810,7 @@ auto LookupBuffer = [](ALCdevice *device, auto id) noexcept -> ALbuffer* BufferSubList &sublist = device->BufferList[static_cast<size_t>(lidx)]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Buffers + static_cast<size_t>(slidx); + return al::to_address(sublist.Buffers->begin() + static_cast<size_t>(slidx)); }; auto LookupFilter = [](ALCdevice *device, auto id) noexcept -> ALfilter* @@ -823,7 +823,7 @@ auto LookupFilter = [](ALCdevice *device, auto id) noexcept -> ALfilter* FilterSubList &sublist = device->FilterList[static_cast<size_t>(lidx)]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Filters + static_cast<size_t>(slidx); + return al::to_address(sublist.Filters->begin() + static_cast<size_t>(slidx)); }; auto LookupEffectSlot = [](ALCcontext *context, auto id) noexcept -> ALeffectslot* @@ -836,7 +836,7 @@ auto LookupEffectSlot = [](ALCcontext *context, auto id) noexcept -> ALeffectslo EffectSlotSubList &sublist{context->mEffectSlotList[static_cast<size_t>(lidx)]}; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.EffectSlots + static_cast<size_t>(slidx); + return al::to_address(sublist.EffectSlots->begin() + static_cast<size_t>(slidx)); }; @@ -1316,11 +1316,11 @@ constexpr ALuint DoubleValsByProp(ALenum prop) struct check_exception : std::exception { }; struct check_size_exception final : check_exception { - const char *what() const noexcept override + [[nodiscard]] auto what() const noexcept -> const char* override { return "check_size_exception"; } }; struct check_value_exception final : check_exception { - const char *what() const noexcept override + [[nodiscard]] auto what() const noexcept -> const char* override { return "check_value_exception"; } }; @@ -1371,21 +1371,22 @@ struct PropType<ALfloat> { static const char *Name() { return "float"; } }; template<> struct PropType<ALdouble> { static const char *Name() { return "double"; } }; -template<typename T> struct HexPrinter { - char mStr[sizeof(T)*2 + 3]{}; + std::array<char,32> mStr{}; + + template<typename T> HexPrinter(T value) { using ST = std::make_signed_t<std::remove_cv_t<T>>; if constexpr(std::is_same_v<ST,int>) - std::snprintf(mStr, std::size(mStr), "0x%x", value); + std::snprintf(mStr.data(), mStr.size(), "0x%x", value); else if constexpr(std::is_same_v<ST,long>) - std::snprintf(mStr, std::size(mStr), "0x%lx", value); + std::snprintf(mStr.data(), mStr.size(), "0x%lx", value); else if constexpr(std::is_same_v<ST,long long>) - std::snprintf(mStr, std::size(mStr), "0x%llx", value); + std::snprintf(mStr.data(), mStr.size(), "0x%llx", value); } - const char *c_str() const noexcept { return mStr; } + [[nodiscard]] auto c_str() const noexcept -> const char* { return mStr.data(); } }; @@ -1579,7 +1580,7 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con * to ensure it isn't currently looping back or reaching the * end. */ - device->waitForMix(); + std::ignore = device->waitForMix(); } return; } @@ -1604,10 +1605,11 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if(!buffer) UNLIKELY return Context->setError(AL_INVALID_VALUE, "Invalid buffer ID %s", std::to_string(values[0]).c_str()); - if(buffer->MappedAccess && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY + if(buffer->MappedAccess + && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY return Context->setError(AL_INVALID_OPERATION, "Setting non-persistently mapped buffer %u", buffer->id); - if(buffer->mCallback && ReadRef(buffer->ref) != 0) UNLIKELY + if(buffer->mCallback && buffer->ref.load(std::memory_order_relaxed) != 0) UNLIKELY return Context->setError(AL_INVALID_OPERATION, "Setting already-set callback buffer %u", buffer->id); @@ -1793,9 +1795,9 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con { Source->Direct.Gain = 1.0f; Source->Direct.GainHF = 1.0f; - Source->Direct.HFReference = LOWPASSFREQREF; + Source->Direct.HFReference = LowPassFreqRef; Source->Direct.GainLF = 1.0f; - Source->Direct.LFReference = HIGHPASSFREQREF; + Source->Direct.LFReference = HighPassFreqRef; } return UpdateSourceProps(Source, Context); } @@ -1921,7 +1923,8 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con ALeffectslot *slot{}; if(values[0]) { - if((slot=LookupEffectSlot(Context, slotid)) == nullptr) UNLIKELY + slot = LookupEffectSlot(Context, slotid); + if(!slot) UNLIKELY return Context->setError(AL_INVALID_VALUE, "Invalid effect ID %s", std::to_string(slotid).c_str()); } @@ -1950,9 +1953,9 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con /* Disable filter */ send.Gain = 1.0f; send.GainHF = 1.0f; - send.HFReference = LOWPASSFREQREF; + send.HFReference = LowPassFreqRef; send.GainLF = 1.0f; - send.LFReference = HIGHPASSFREQREF; + send.LFReference = HighPassFreqRef; } /* We must force an update if the current auxiliary slot is valid @@ -3404,90 +3407,94 @@ FORCE_ALIGN void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALu std::unique_lock<std::mutex> buflock{device->BufferLock}; const size_t NewListStart{source->mQueue.size()}; - ALbufferQueueItem *BufferList{nullptr}; - for(ALsizei i{0};i < nb;i++) - { - bool fmt_mismatch{false}; - ALbuffer *buffer{nullptr}; - if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == nullptr) + try { + ALbufferQueueItem *BufferList{nullptr}; + for(ALsizei i{0};i < nb;i++) { - context->setError(AL_INVALID_NAME, "Queueing invalid buffer ID %u", buffers[i]); - goto buffer_error; - } - if(buffer) - { - if(buffer->mSampleRate < 1) + bool fmt_mismatch{false}; + ALbuffer *buffer{buffers[i] ? LookupBuffer(device, buffers[i]) : nullptr}; + if(buffers[i] && !buffer) { - context->setError(AL_INVALID_OPERATION, "Queueing buffer %u with no format", - buffer->id); - goto buffer_error; + context->setError(AL_INVALID_NAME, "Queueing invalid buffer ID %u", buffers[i]); + throw std::exception{}; } - if(buffer->mCallback) + if(buffer) { - context->setError(AL_INVALID_OPERATION, "Queueing callback buffer %u", buffer->id); - goto buffer_error; + if(buffer->mSampleRate < 1) + { + context->setError(AL_INVALID_OPERATION, "Queueing buffer %u with no format", + buffer->id); + throw std::exception{}; + } + if(buffer->mCallback) + { + context->setError(AL_INVALID_OPERATION, "Queueing callback buffer %u", + buffer->id); + throw std::exception{}; + } + if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) + { + context->setError(AL_INVALID_OPERATION, + "Queueing non-persistently mapped buffer %u", buffer->id); + throw std::exception{}; + } } - if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) + + source->mQueue.emplace_back(); + if(!BufferList) + BufferList = &source->mQueue.back(); + else { - context->setError(AL_INVALID_OPERATION, - "Queueing non-persistently mapped buffer %u", buffer->id); - goto buffer_error; + auto &item = source->mQueue.back(); + BufferList->mNext.store(&item, std::memory_order_relaxed); + BufferList = &item; } - } - - source->mQueue.emplace_back(); - if(!BufferList) - BufferList = &source->mQueue.back(); - else - { - auto &item = source->mQueue.back(); - BufferList->mNext.store(&item, std::memory_order_relaxed); - BufferList = &item; - } - if(!buffer) continue; - BufferList->mBlockAlign = buffer->mBlockAlign; - BufferList->mSampleLen = buffer->mSampleLen; - BufferList->mLoopEnd = buffer->mSampleLen; - BufferList->mSamples = buffer->mData.data(); - BufferList->mBuffer = buffer; - IncrementRef(buffer->ref); - - if(BufferFmt == nullptr) - BufferFmt = buffer; - else - { - fmt_mismatch |= BufferFmt->mSampleRate != buffer->mSampleRate; - fmt_mismatch |= BufferFmt->mChannels != buffer->mChannels; - fmt_mismatch |= BufferFmt->mType != buffer->mType; - if(BufferFmt->isBFormat()) + if(!buffer) continue; + BufferList->mBlockAlign = buffer->mBlockAlign; + BufferList->mSampleLen = buffer->mSampleLen; + BufferList->mLoopEnd = buffer->mSampleLen; + BufferList->mSamples = buffer->mData.data(); + BufferList->mBuffer = buffer; + IncrementRef(buffer->ref); + + if(BufferFmt == nullptr) + BufferFmt = buffer; + else { - fmt_mismatch |= BufferFmt->mAmbiLayout != buffer->mAmbiLayout; - fmt_mismatch |= BufferFmt->mAmbiScaling != buffer->mAmbiScaling; + fmt_mismatch |= BufferFmt->mSampleRate != buffer->mSampleRate; + fmt_mismatch |= BufferFmt->mChannels != buffer->mChannels; + fmt_mismatch |= BufferFmt->mType != buffer->mType; + if(BufferFmt->isBFormat()) + { + fmt_mismatch |= BufferFmt->mAmbiLayout != buffer->mAmbiLayout; + fmt_mismatch |= BufferFmt->mAmbiScaling != buffer->mAmbiScaling; + } + fmt_mismatch |= BufferFmt->mAmbiOrder != buffer->mAmbiOrder; } - fmt_mismatch |= BufferFmt->mAmbiOrder != buffer->mAmbiOrder; - } - if(fmt_mismatch) UNLIKELY - { - context->setError(AL_INVALID_OPERATION, "Queueing buffer with mismatched format\n" - " Expected: %uhz, %s, %s ; Got: %uhz, %s, %s\n", BufferFmt->mSampleRate, - NameFromFormat(BufferFmt->mType), NameFromFormat(BufferFmt->mChannels), - buffer->mSampleRate, NameFromFormat(buffer->mType), - NameFromFormat(buffer->mChannels)); - - buffer_error: - /* A buffer failed (invalid ID or format), so unlock and release - * each buffer we had. - */ - auto iter = source->mQueue.begin() + ptrdiff_t(NewListStart); - for(;iter != source->mQueue.end();++iter) + if(fmt_mismatch) UNLIKELY { - if(ALbuffer *buf{iter->mBuffer}) - DecrementRef(buf->ref); + context->setError(AL_INVALID_OPERATION, "Queueing buffer with mismatched format\n" + " Expected: %uhz, %s, %s ; Got: %uhz, %s, %s\n", BufferFmt->mSampleRate, + NameFromFormat(BufferFmt->mType), NameFromFormat(BufferFmt->mChannels), + buffer->mSampleRate, NameFromFormat(buffer->mType), + NameFromFormat(buffer->mChannels)); + throw std::exception{}; } - source->mQueue.resize(NewListStart); - return; } } + catch(...) { + /* A buffer failed (invalid ID or format), or there was some other + * unexpected error, so unlock and release each buffer we had. + */ + auto iter = source->mQueue.begin() + ptrdiff_t(NewListStart); + for(;iter != source->mQueue.end();++iter) + { + if(ALbuffer *buf{iter->mBuffer}) + DecrementRef(buf->ref); + } + source->mQueue.resize(NewListStart); + return; + } /* All buffers good. */ buflock.unlock(); @@ -3565,17 +3572,17 @@ ALsource::ALsource() { Direct.Gain = 1.0f; Direct.GainHF = 1.0f; - Direct.HFReference = LOWPASSFREQREF; + Direct.HFReference = LowPassFreqRef; Direct.GainLF = 1.0f; - Direct.LFReference = HIGHPASSFREQREF; + Direct.LFReference = HighPassFreqRef; for(auto &send : Send) { send.Slot = nullptr; send.Gain = 1.0f; send.GainHF = 1.0f; - send.HFReference = LOWPASSFREQREF; + send.HFReference = LowPassFreqRef; send.GainLF = 1.0f; - send.LFReference = HIGHPASSFREQREF; + send.LFReference = HighPassFreqRef; } } @@ -3632,18 +3639,15 @@ SourceSubList::~SourceSubList() { const int idx{al::countr_zero(usemask)}; usemask &= ~(1_u64 << idx); - std::destroy_at(Sources+idx); + std::destroy_at(al::to_address(Sources->begin() + idx)); } FreeMask = ~usemask; - al_free(Sources); + SubListAllocator{}.deallocate(Sources, 1); Sources = nullptr; } #ifdef ALSOFT_EAX -constexpr const ALsource::EaxFxSlotIds ALsource::eax4_fx_slot_ids; -constexpr const ALsource::EaxFxSlotIds ALsource::eax5_fx_slot_ids; - void ALsource::eaxInitialize(ALCcontext *context) noexcept { assert(context != nullptr); @@ -3916,27 +3920,30 @@ void ALsource::eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept // Active FX slots. // - for (auto i = 0; i < EAX50_MAX_ACTIVE_FXSLOTS; ++i) { + for(size_t i{0};i < EAX50_MAX_ACTIVE_FXSLOTS;++i) + { auto& dst_id = dst.active_fx_slots.guidActiveFXSlots[i]; - if (i < EAX40_MAX_ACTIVE_FXSLOTS) { + if(i < EAX40_MAX_ACTIVE_FXSLOTS) + { const auto& src_id = src.active_fx_slots.guidActiveFXSlots[i]; - if (src_id == EAX_NULL_GUID) + if(src_id == EAX_NULL_GUID) dst_id = EAX_NULL_GUID; - else if (src_id == EAX_PrimaryFXSlotID) + else if(src_id == EAX_PrimaryFXSlotID) dst_id = EAX_PrimaryFXSlotID; - else if (src_id == EAXPROPERTYID_EAX40_FXSlot0) + else if(src_id == EAXPROPERTYID_EAX40_FXSlot0) dst_id = EAXPROPERTYID_EAX50_FXSlot0; - else if (src_id == EAXPROPERTYID_EAX40_FXSlot1) + else if(src_id == EAXPROPERTYID_EAX40_FXSlot1) dst_id = EAXPROPERTYID_EAX50_FXSlot1; - else if (src_id == EAXPROPERTYID_EAX40_FXSlot2) + else if(src_id == EAXPROPERTYID_EAX40_FXSlot2) dst_id = EAXPROPERTYID_EAX50_FXSlot2; - else if (src_id == EAXPROPERTYID_EAX40_FXSlot3) + else if(src_id == EAXPROPERTYID_EAX40_FXSlot3) dst_id = EAXPROPERTYID_EAX50_FXSlot3; else assert(false && "Unknown active FX slot ID."); - } else + } + else dst_id = EAX_NULL_GUID; } @@ -4067,9 +4074,9 @@ void ALsource::eax_update_direct_filter() const auto& direct_param = eax_create_direct_filter_param(); Direct.Gain = direct_param.gain; Direct.GainHF = direct_param.gain_hf; - Direct.HFReference = LOWPASSFREQREF; + Direct.HFReference = LowPassFreqRef; Direct.GainLF = 1.0f; - Direct.LFReference = HIGHPASSFREQREF; + Direct.LFReference = HighPassFreqRef; mPropsDirty = true; } @@ -4358,7 +4365,7 @@ void ALsource::eax4_set(const EaxCall& call, Eax4Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - eax4_defer_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots); + eax4_defer_active_fx_slot_id(call, al::span{props.active_fx_slots.guidActiveFXSlots}); break; default: @@ -4439,7 +4446,7 @@ void ALsource::eax5_set(const EaxCall& call, Eax5Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - eax5_defer_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots); + eax5_defer_active_fx_slot_id(call, al::span{props.active_fx_slots.guidActiveFXSlots}); break; case EAXSOURCE_MACROFXFACTOR: @@ -4729,7 +4736,8 @@ void ALsource::eax4_get(const EaxCall& call, const Eax4Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots, EAX40_MAX_ACTIVE_FXSLOTS); + eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots.data(), + EAX40_MAX_ACTIVE_FXSLOTS); break; default: @@ -4801,7 +4809,8 @@ void ALsource::eax5_get(const EaxCall& call, const Eax5Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots, EAX50_MAX_ACTIVE_FXSLOTS); + eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots.data(), + EAX50_MAX_ACTIVE_FXSLOTS); break; case EAXSOURCE_MACROFXFACTOR: @@ -4841,9 +4850,9 @@ void ALsource::eax_set_al_source_send(ALeffectslot *slot, size_t sendidx, const auto &send = Send[sendidx]; send.Gain = filter.gain; send.GainHF = filter.gain_hf; - send.HFReference = LOWPASSFREQREF; + send.HFReference = LowPassFreqRef; send.GainLF = 1.0f; - send.LFReference = HIGHPASSFREQREF; + send.LFReference = HighPassFreqRef; if(slot != nullptr) IncrementRef(slot->ref); |