diff options
-rw-r--r-- | al/source.cpp | 252 | ||||
-rw-r--r-- | al/source.h | 58 | ||||
-rw-r--r-- | alc/inprogext.h | 8 | ||||
-rw-r--r-- | alc/mixvoice.cpp | 133 |
4 files changed, 96 insertions, 355 deletions
diff --git a/al/source.cpp b/al/source.cpp index 98c52816..4bdf51fe 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -206,7 +206,7 @@ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, std::chrono const ALbufferlistitem *BufferList{Source->queue}; while(BufferList && BufferList != Current) { - readPos += int64_t{BufferList->mMaxSamples} << 32; + readPos += int64_t{BufferList->mSampleLen} << 32; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } readPos = minu64(readPos, 0x7fffffffffffffff_u64); @@ -253,16 +253,14 @@ ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, std::chrono:: const ALbuffer *BufferFmt{nullptr}; while(BufferList && BufferList != Current) { - for(ALuint i{0};!BufferFmt && i < BufferList->mNumBuffers;++i) - BufferFmt = (*BufferList)[i]; - readPos += int64_t{BufferList->mMaxSamples} << FRACTIONBITS; + if(!BufferFmt) BufferFmt = BufferList->mBuffer; + readPos += int64_t{BufferList->mSampleLen} << FRACTIONBITS; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } while(BufferList && !BufferFmt) { - for(ALuint i{0};!BufferFmt && i < BufferList->mNumBuffers;++i) - BufferFmt = (*BufferList)[i]; + BufferFmt = BufferList->mBuffer; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } assert(BufferFmt != nullptr); @@ -315,12 +313,11 @@ ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) while(BufferList) { - for(ALuint i{0};!BufferFmt && i < BufferList->mNumBuffers;++i) - BufferFmt = (*BufferList)[i]; + if(!BufferFmt) BufferFmt = BufferList->mBuffer; readFin |= (BufferList == Current); - totalBufferLen += BufferList->mMaxSamples; - if(!readFin) readPos += BufferList->mMaxSamples; + totalBufferLen += BufferList->mSampleLen; + if(!readFin) readPos += BufferList->mSampleLen; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } @@ -392,11 +389,9 @@ ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALsizei *frac) /* Find the first valid Buffer in the Queue */ BufferList = Source->queue; - while(BufferList) + while(BufferList && !BufferFmt) { - for(ALuint i{0};!BufferFmt && i < BufferList->mNumBuffers;i++) - BufferFmt = (*BufferList)[i]; - if(BufferFmt) break; + BufferFmt = BufferList->mBuffer; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } if(!BufferFmt) @@ -464,7 +459,7 @@ ALboolean ApplyOffset(ALsource *Source, ALvoice *voice) ALbufferlistitem *BufferList{Source->queue}; while(BufferList && totalBufferLen <= offset) { - if(static_cast<ALuint>(BufferList->mMaxSamples) > offset-totalBufferLen) + if(BufferList->mSampleLen > offset-totalBufferLen) { /* Offset is in this buffer */ voice->mPosition.store(offset - totalBufferLen, std::memory_order_relaxed); @@ -472,7 +467,7 @@ ALboolean ApplyOffset(ALsource *Source, ALvoice *voice) voice->mCurrentBuffer.store(BufferList, std::memory_order_release); return AL_TRUE; } - totalBufferLen += BufferList->mMaxSamples; + totalBufferLen += BufferList->mSampleLen; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } @@ -1197,12 +1192,9 @@ bool SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a if(buffer != nullptr) { /* Add the selected buffer to a one-item queue */ - auto newlist = static_cast<ALbufferlistitem*>(al_calloc(alignof(void*), - ALbufferlistitem::Sizeof(1u))); - newlist->mNext.store(nullptr, std::memory_order_relaxed); - newlist->mMaxSamples = buffer->SampleLen; - newlist->mNumBuffers = 1; - newlist->mBuffers[0] = buffer; + auto newlist = new ALbufferlistitem{}; + newlist->mSampleLen = buffer->SampleLen; + newlist->mBuffer = buffer; IncrementRef(buffer->ref); /* Source is now Static */ @@ -1220,13 +1212,11 @@ bool SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a /* Delete all elements in the previous queue */ while(oldlist != nullptr) { - ALbufferlistitem *temp{oldlist}; + std::unique_ptr<ALbufferlistitem> temp{oldlist}; oldlist = temp->mNext.load(std::memory_order_relaxed); - std::for_each(temp->begin(), temp->end(), - [](ALbuffer *buffer) -> void - { if(buffer) DecrementRef(buffer->ref); }); - al_free(temp); + if(ALbuffer *buffer{temp->mBuffer}) + DecrementRef(buffer->ref); } return true; @@ -1769,8 +1759,7 @@ bool GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a case AL_BUFFER: CHECKSIZE(values, 1); BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : nullptr; - values[0] = (BufferList && !BufferList->empty() && BufferList->front()) ? - BufferList->front()->id : 0; + values[0] = (BufferList && BufferList->mBuffer) ? BufferList->mBuffer->id : 0; return true; case AL_SOURCE_STATE: @@ -1786,7 +1775,7 @@ bool GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a { ALsizei count{0}; do { - count += BufferList->mNumBuffers; + ++count; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } while(BufferList != nullptr); values[0] = count; @@ -1815,7 +1804,7 @@ bool GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a while(BufferList && BufferList != Current) { - played += BufferList->mNumBuffers; + ++played; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } values[0] = played; @@ -2729,7 +2718,7 @@ START_API_FUNC * length buffer. */ ALbufferlistitem *BufferList{source->queue}; - while(BufferList && BufferList->mMaxSamples == 0) + while(BufferList && BufferList->mSampleLen == 0) BufferList = BufferList->mNext.load(std::memory_order_relaxed); /* If there's nothing to play, go right to stopped. */ @@ -2807,15 +2796,11 @@ START_API_FUNC voice->mPositionFrac.load(std::memory_order_relaxed) != 0 || voice->mCurrentBuffer.load(std::memory_order_relaxed) != BufferList; - auto buffer = std::find_if(BufferList->cbegin(), BufferList->cend(), - std::bind(std::not_equal_to<const ALbuffer*>{}, _1, nullptr)); - if(buffer != BufferList->cend()) - { - voice->mFrequency = (*buffer)->Frequency; - voice->mFmtChannels = (*buffer)->mFmtChannels; - voice->mNumChannels = ChannelsFromFmt((*buffer)->mFmtChannels); - voice->mSampleSize = BytesFromFmt((*buffer)->mFmtType); - } + ALbuffer *buffer{BufferList->mBuffer}; + voice->mFrequency = buffer->Frequency; + voice->mFmtChannels = buffer->mFmtChannels; + voice->mNumChannels = ChannelsFromFmt(buffer->mFmtChannels); + voice->mSampleSize = BytesFromFmt(buffer->mFmtType); /* Clear the stepping value so the mixer knows not to mix this until * the update gets applied. @@ -3101,11 +3086,9 @@ START_API_FUNC ALCdevice *device{context->mDevice.get()}; ALbuffer *BufferFmt{nullptr}; ALbufferlistitem *BufferList{source->queue}; - while(BufferList) + while(BufferList && !BufferFmt) { - for(ALuint i{0};!BufferFmt && i < BufferList->mNumBuffers;i++) - BufferFmt = (*BufferList)[i]; - if(BufferFmt) break; + BufferFmt = BufferList->mBuffer; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } @@ -3123,128 +3106,22 @@ START_API_FUNC if(!BufferListStart) { - BufferListStart = static_cast<ALbufferlistitem*>(al_calloc(alignof(void*), - ALbufferlistitem::Sizeof(1u))); + BufferListStart = new ALbufferlistitem{}; BufferList = BufferListStart; } else { - auto item = static_cast<ALbufferlistitem*>(al_calloc(alignof(void*), - ALbufferlistitem::Sizeof(1u))); + auto item = new ALbufferlistitem{}; BufferList->mNext.store(item, std::memory_order_relaxed); BufferList = item; } BufferList->mNext.store(nullptr, std::memory_order_relaxed); - BufferList->mMaxSamples = buffer ? buffer->SampleLen : 0; - BufferList->mNumBuffers = 1; - BufferList->mBuffers[0] = buffer; - if(!buffer) continue; - - IncrementRef(buffer->ref); - - if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) - { - context->setError(AL_INVALID_OPERATION, "Queueing non-persistently mapped buffer %u", - buffer->id); - goto buffer_error; - } - - if(BufferFmt == nullptr) - BufferFmt = buffer; - else if(BufferFmt->Frequency != buffer->Frequency || - BufferFmt->mFmtChannels != buffer->mFmtChannels || - BufferFmt->OriginalType != buffer->OriginalType) - { - context->setError(AL_INVALID_OPERATION, "Queueing buffer with mismatched format"); - - buffer_error: - /* A buffer failed (invalid ID or format), so unlock and release - * each buffer we had. */ - while(BufferListStart) - { - ALbufferlistitem *next = BufferListStart->mNext.load(std::memory_order_relaxed); - std::for_each(BufferListStart->begin(), BufferListStart->end(), - [](ALbuffer *buffer) -> void - { if(buffer) DecrementRef(buffer->ref); }); - al_free(BufferListStart); - BufferListStart = next; - } - return; - } - } - /* All buffers good. */ - buflock.unlock(); - - /* Source is now streaming */ - source->SourceType = AL_STREAMING; - - if(!(BufferList=source->queue)) - source->queue = BufferListStart; - else - { - ALbufferlistitem *next; - while((next=BufferList->mNext.load(std::memory_order_relaxed)) != nullptr) - BufferList = next; - BufferList->mNext.store(BufferListStart, std::memory_order_release); - } -} -END_API_FUNC - -AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, const ALuint *buffers) -START_API_FUNC -{ - ContextRef context{GetContextRef()}; - if UNLIKELY(!context) return; - - if UNLIKELY(nb < 0) - context->setError(AL_INVALID_VALUE, "Queueing %d buffer layers", nb); - if UNLIKELY(nb <= 0) return; - - std::lock_guard<std::mutex> _{context->mSourceLock}; - ALsource *source{LookupSource(context.get(),src)}; - if UNLIKELY(!source) - SETERR_RETURN(context, AL_INVALID_NAME,, "Invalid source ID %u", src); - - /* Can't queue on a Static Source */ - if UNLIKELY(source->SourceType == AL_STATIC) - SETERR_RETURN(context, AL_INVALID_OPERATION,, "Queueing onto static source %u", src); - - /* Check for a valid Buffer, for its frequency and format */ - ALCdevice *device{context->mDevice.get()}; - ALbuffer *BufferFmt{nullptr}; - ALbufferlistitem *BufferList{source->queue}; - while(BufferList) - { - for(ALuint i{0};!BufferFmt && i < BufferList->mNumBuffers;i++) - BufferFmt = (*BufferList)[i]; - if(BufferFmt) break; - BufferList = BufferList->mNext.load(std::memory_order_relaxed); - } - - std::unique_lock<std::mutex> buflock{device->BufferLock}; - auto BufferListStart = static_cast<ALbufferlistitem*>(al_calloc(alignof(void*), - ALbufferlistitem::Sizeof(nb))); - BufferList = BufferListStart; - BufferList->mNext.store(nullptr, std::memory_order_relaxed); - BufferList->mMaxSamples = 0; - BufferList->mNumBuffers = 0; - - for(ALsizei i{0};i < nb;i++) - { - ALbuffer *buffer{nullptr}; - if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == nullptr) - { - context->setError(AL_INVALID_NAME, "Queueing invalid buffer ID %u", buffers[i]); - goto buffer_error; - } - - BufferList->mBuffers[BufferList->mNumBuffers++] = buffer; + BufferList->mSampleLen = buffer ? buffer->SampleLen : 0; + BufferList->mBuffer = buffer; if(!buffer) continue; IncrementRef(buffer->ref); - BufferList->mMaxSamples = maxu(BufferList->mMaxSamples, buffer->SampleLen); - if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) { context->setError(AL_INVALID_OPERATION, "Queueing non-persistently mapped buffer %u", @@ -3265,12 +3142,9 @@ START_API_FUNC * each buffer we had. */ while(BufferListStart) { - ALbufferlistitem *next{BufferListStart->mNext.load(std::memory_order_relaxed)}; - std::for_each(BufferListStart->begin(), BufferListStart->end(), - [](ALbuffer *buffer) -> void - { if(buffer) DecrementRef(buffer->ref); }); - al_free(BufferListStart); - BufferListStart = next; + std::unique_ptr<ALbufferlistitem> head{BufferListStart}; + BufferListStart = head->mNext.load(std::memory_order_relaxed); + if(ALbuffer *buffer{head->mBuffer}) DecrementRef(buffer->ref); } return; } @@ -3325,7 +3199,7 @@ START_API_FUNC if UNLIKELY(BufferList == Current) SETERR_RETURN(context, AL_INVALID_VALUE,, "Unqueueing pending buffers"); - ALuint i{BufferList->mNumBuffers}; + ALuint i{1u}; while(i < static_cast<ALuint>(nb)) { /* If the next bufferlist to check is NULL or is the current one, it's @@ -3336,47 +3210,22 @@ START_API_FUNC SETERR_RETURN(context, AL_INVALID_VALUE,, "Unqueueing pending buffers"); BufferList = next; - i += BufferList->mNumBuffers; + ++i; } while(nb > 0) { - ALbufferlistitem *head{source->queue}; - ALbufferlistitem *next{head->mNext.load(std::memory_order_relaxed)}; - for(i = 0;i < head->mNumBuffers && nb > 0;i++,nb--) - { - ALbuffer *buffer{(*head)[i]}; - if(!buffer) - *(buffers++) = 0; - else - { - *(buffers++) = buffer->id; - DecrementRef(buffer->ref); - } - } - if(i < head->mNumBuffers) + std::unique_ptr<ALbufferlistitem> head{source->queue}; + source->queue = head->mNext.load(std::memory_order_relaxed); + + if(ALbuffer *buffer{head->mBuffer}) { - /* This head has some buffers left over, so move them to the front - * and update the sample and buffer count. - */ - ALuint max_length{0}; - ALuint j{0}; - while(i < head->mNumBuffers) - { - ALbuffer *buffer{(*head)[i++]}; - if(buffer) max_length = maxu(max_length, buffer->SampleLen); - head->mBuffers[j++] = buffer; - } - head->mMaxSamples = max_length; - head->mNumBuffers = j; - break; + *(buffers++) = buffer->id; + DecrementRef(buffer->ref); } - - /* Otherwise, free this item and set the source queue head to the next - * one. - */ - al_free(head); - source->queue = next; + else + *(buffers++) = 0; + --nb; } } END_API_FUNC @@ -3453,12 +3302,9 @@ ALsource::~ALsource() ALbufferlistitem *BufferList{queue}; while(BufferList != nullptr) { - ALbufferlistitem *next{BufferList->mNext.load(std::memory_order_relaxed)}; - std::for_each(BufferList->begin(), BufferList->end(), - [](ALbuffer *buffer) -> void - { if(buffer) DecrementRef(buffer->ref); }); - al_free(BufferList); - BufferList = next; + std::unique_ptr<ALbufferlistitem> head{BufferList}; + BufferList = head->mNext.load(std::memory_order_relaxed); + if(ALbuffer *buffer{BufferList->mBuffer}) DecrementRef(buffer->ref); } queue = nullptr; diff --git a/al/source.h b/al/source.h index a5d10cf9..05037fd3 100644 --- a/al/source.h +++ b/al/source.h @@ -10,6 +10,7 @@ #include "AL/alc.h" #include "alcontext.h" +#include "almalloc.h" #include "alnumeric.h" #include "alu.h" #include "vector.h" @@ -23,58 +24,11 @@ struct ALeffectslot; #define INVALID_VOICE_IDX static_cast<ALuint>(-1) struct ALbufferlistitem { - using element_type = ALbuffer*; - using value_type = ALbuffer*; - using index_type = size_t; - using difference_type = ptrdiff_t; - - using pointer = ALbuffer**; - using const_pointer = ALbuffer*const*; - using reference = ALbuffer*&; - using const_reference = ALbuffer*const&; - - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - - - std::atomic<ALbufferlistitem*> mNext; - ALuint mMaxSamples; - ALuint mNumBuffers; - element_type mBuffers[]; - - static constexpr size_t Sizeof(size_t num_buffers) noexcept - { - return maxz(offsetof(ALbufferlistitem, mBuffers) + sizeof(element_type)*num_buffers, - sizeof(ALbufferlistitem)); - } - - reference front() { return mBuffers[0]; } - const_reference front() const { return mBuffers[0]; } - reference back() { return mBuffers[mNumBuffers-1]; } - const_reference back() const { return mBuffers[mNumBuffers-1]; } - reference operator[](index_type idx) { return mBuffers[idx]; } - const_reference operator[](index_type idx) const { return mBuffers[idx]; } - pointer data() noexcept { return mBuffers; } - const_pointer data() const noexcept { return mBuffers; } - - index_type size() const noexcept { return mNumBuffers; } - bool empty() const noexcept { return mNumBuffers == 0; } - - iterator begin() noexcept { return mBuffers; } - iterator end() noexcept { return mBuffers+mNumBuffers; } - const_iterator begin() const noexcept { return mBuffers; } - const_iterator end() const noexcept { return mBuffers+mNumBuffers; } - const_iterator cbegin() const noexcept { return mBuffers; } - const_iterator cend() const noexcept { return mBuffers+mNumBuffers; } - - reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; } - reverse_iterator rend() noexcept { return reverse_iterator{begin()}; } - const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; } - const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; } - const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; } - const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; } + std::atomic<ALbufferlistitem*> mNext{nullptr}; + ALuint mSampleLen{0u}; + ALbuffer *mBuffer{nullptr}; + + DEF_NEWDEL(ALbufferlistitem) }; diff --git a/alc/inprogext.h b/alc/inprogext.h index 15881b59..ad3ea288 100644 --- a/alc/inprogext.h +++ b/alc/inprogext.h @@ -72,14 +72,6 @@ AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values); #endif #endif -#ifndef AL_SOFT_buffer_layers -#define AL_SOFT_buffer_layers -typedef void (AL_APIENTRY*LPALSOURCEQUEUEBUFFERLAYERSSOFT)(ALuint src, ALsizei nb, const ALuint *buffers); -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, const ALuint *buffers); -#endif -#endif - #ifndef AL_SOFT_effect_chain #define AL_SOFT_effect_chain #define AL_EFFECTSLOT_TARGET_SOFT 0xf000 diff --git a/alc/mixvoice.cpp b/alc/mixvoice.cpp index cf3eeb50..295b1352 100644 --- a/alc/mixvoice.cpp +++ b/alc/mixvoice.cpp @@ -372,7 +372,7 @@ inline void LoadSampleArray(ALfloat *RESTRICT dst, const al::byte *src, ALint sr const SampleType *RESTRICT ssrc{reinterpret_cast<const SampleType*>(src)}; for(ALsizei i{0};i < samples;i++) - dst[i] += FmtTypeTraits<T>::to_float(ssrc[i*srcstep]); + dst[i] = FmtTypeTraits<T>::to_float(ssrc[i*srcstep]); } void LoadSamples(ALfloat *RESTRICT dst, const al::byte *src, ALint srcstep, FmtType srctype, @@ -395,12 +395,9 @@ ALfloat *LoadBufferStatic(ALbufferlistitem *BufferListItem, ALbufferlistitem *&B const ALsizei NumChannels, const ALsizei SampleSize, const ALsizei chan, ALuint DataPosInt, al::span<ALfloat> SrcBuffer) { - /* TODO: For static sources, loop points are taken from the first buffer - * (should be adjusted by any buffer offset, to possibly be added later). - */ - const ALbuffer *Buffer0{BufferListItem->front()}; - const ALuint LoopStart{Buffer0->LoopStart}; - const ALuint LoopEnd{Buffer0->LoopEnd}; + const ALbuffer *Buffer{BufferListItem->mBuffer}; + const ALuint LoopStart{Buffer->LoopStart}; + const ALuint LoopEnd{Buffer->LoopEnd}; ASSUME(LoopStart >= 0); ASSUME(LoopEnd > LoopStart); @@ -409,75 +406,37 @@ ALfloat *LoadBufferStatic(ALbufferlistitem *BufferListItem, ALbufferlistitem *&B { BufferLoopItem = nullptr; - auto load_buffer = [DataPosInt,NumChannels,SampleSize,chan,SrcBuffer](size_t CompLen, const ALbuffer *buffer) -> size_t - { - if(DataPosInt >= buffer->SampleLen) - return CompLen; - - /* Load what's left to play from the buffer */ - const size_t DataSize{std::min<size_t>(SrcBuffer.size(), - buffer->SampleLen - DataPosInt)}; - CompLen = std::max(CompLen, DataSize); - - const al::byte *Data{buffer->mData.data()}; - Data += (DataPosInt*NumChannels + chan)*SampleSize; - - LoadSamples(SrcBuffer.data(), Data, NumChannels, buffer->mFmtType, DataSize); - return CompLen; - }; - /* It's impossible to have a buffer list item with no entries. */ - ASSUME(BufferListItem->mNumBuffers > 0); - SrcBuffer = SrcBuffer.subspan(std::accumulate(BufferListItem->begin(), - BufferListItem->end(), size_t{0u}, load_buffer)); + /* Load what's left to play from the buffer */ + const size_t DataSize{minz(SrcBuffer.size(), Buffer->SampleLen-DataPosInt)}; + + const al::byte *Data{Buffer->mData.data()}; + Data += (DataPosInt*NumChannels + chan)*SampleSize; + + LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize); + SrcBuffer = SrcBuffer.subspan(DataSize); } else { - const al::span<ALfloat> SrcData{SrcBuffer.first( - std::min<size_t>(SrcBuffer.size(), LoopEnd - DataPosInt))}; + /* Load what's left of this loop iteration */ + const size_t DataSize{minz(SrcBuffer.size(), LoopEnd-DataPosInt)}; - auto load_buffer = [DataPosInt,NumChannels,SampleSize,chan,SrcData](size_t CompLen, const ALbuffer *buffer) -> size_t - { - if(DataPosInt >= buffer->SampleLen) - return CompLen; + const al::byte *Data{Buffer->mData.data()}; + Data += (DataPosInt*NumChannels + chan)*SampleSize; - /* Load what's left of this loop iteration */ - const size_t DataSize{std::min<size_t>(SrcData.size(), - buffer->SampleLen - DataPosInt)}; - CompLen = std::max(CompLen, DataSize); - - const al::byte *Data{buffer->mData.data()}; - Data += (DataPosInt*NumChannels + chan)*SampleSize; - - LoadSamples(SrcData.data(), Data, NumChannels, buffer->mFmtType, DataSize); - return CompLen; - }; - ASSUME(BufferListItem->mNumBuffers > 0); - SrcBuffer = SrcBuffer.subspan(std::accumulate(BufferListItem->begin(), - BufferListItem->end(), size_t{0u}, load_buffer)); + LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize); + SrcBuffer = SrcBuffer.subspan(DataSize); + /* Load any repeats of the loop we can to fill the buffer. */ const auto LoopSize = static_cast<size_t>(LoopEnd - LoopStart); while(!SrcBuffer.empty()) { - const al::span<ALfloat> SrcData{SrcBuffer.first( - std::min<size_t>(SrcBuffer.size(), LoopSize))}; - - auto load_buffer_loop = [LoopStart,NumChannels,SampleSize,chan,SrcData](size_t CompLen, const ALbuffer *buffer) -> size_t - { - if(LoopStart >= buffer->SampleLen) - return CompLen; - - const size_t DataSize{std::min<size_t>(SrcData.size(), - buffer->SampleLen-LoopStart)}; - CompLen = std::max(CompLen, DataSize); + const size_t DataSize{minz(SrcBuffer.size(), LoopSize)}; - const al::byte *Data{buffer->mData.data()}; - Data += (LoopStart*NumChannels + chan)*SampleSize; + const al::byte *Data{Buffer->mData.data()}; + Data += (LoopStart*NumChannels + chan)*SampleSize; - LoadSamples(SrcData.data(), Data, NumChannels, buffer->mFmtType, DataSize); - return CompLen; - }; - SrcBuffer = SrcBuffer.subspan(std::accumulate(BufferListItem->begin(), - BufferListItem->end(), size_t{0u}, load_buffer_loop)); + LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize); + SrcBuffer = SrcBuffer.subspan(DataSize); } } return SrcBuffer.begin(); @@ -490,35 +449,24 @@ ALfloat *LoadBufferQueue(ALbufferlistitem *BufferListItem, ALbufferlistitem *Buf /* Crawl the buffer queue to fill in the temp buffer */ while(BufferListItem && !SrcBuffer.empty()) { - if(DataPosInt >= BufferListItem->mMaxSamples) + ALbuffer *Buffer{BufferListItem->mBuffer}; + if(!(Buffer && DataPosInt < Buffer->SampleLen)) { - DataPosInt -= BufferListItem->mMaxSamples; + if(Buffer) DataPosInt -= Buffer->SampleLen; BufferListItem = BufferListItem->mNext.load(std::memory_order_acquire); if(!BufferListItem) BufferListItem = BufferLoopItem; continue; } - auto load_buffer = [DataPosInt,NumChannels,SampleSize,chan,SrcBuffer](size_t CompLen, const ALbuffer *buffer) -> size_t - { - if(!buffer) return CompLen; - if(DataPosInt >= buffer->SampleLen) - return CompLen; + const size_t DataSize{std::min<size_t>(SrcBuffer.size(), Buffer->SampleLen-DataPosInt)}; - const size_t DataSize{std::min<size_t>(SrcBuffer.size(), buffer->SampleLen-DataPosInt)}; - CompLen = std::max(CompLen, DataSize); + const al::byte *Data{Buffer->mData.data()}; + Data += (DataPosInt*NumChannels + chan)*SampleSize; - const al::byte *Data{buffer->mData.data()}; - Data += (DataPosInt*NumChannels + chan)*SampleSize; + LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataSize); + SrcBuffer = SrcBuffer.subspan(DataSize); + if(SrcBuffer.empty()) break; - LoadSamples(SrcBuffer.data(), Data, NumChannels, buffer->mFmtType, DataSize); - return CompLen; - }; - ASSUME(BufferListItem->mNumBuffers > 0); - SrcBuffer = SrcBuffer.subspan(std::accumulate(BufferListItem->begin(), - BufferListItem->end(), size_t{0u}, load_buffer)); - - if(SrcBuffer.empty()) - break; DataPosInt = 0; BufferListItem = BufferListItem->mNext.load(std::memory_order_acquire); if(!BufferListItem) BufferListItem = BufferLoopItem; @@ -640,10 +588,11 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc ALvoice::ChannelData &chandata = voice->mChans[chan]; const al::span<ALfloat> SrcData{Device->SourceData, SrcBufferSize}; - /* Load the previous samples into the source data first, and clear the rest. */ + /* Load the previous samples into the source data first, then load + * what we can from the buffer queue. + */ auto srciter = std::copy_n(chandata.mPrevSamples.begin(), MAX_RESAMPLE_PADDING, SrcData.begin()); - std::fill(srciter, SrcData.end(), 0.0f); if UNLIKELY(!BufferListItem) srciter = std::copy(chandata.mPrevSamples.begin()+MAX_RESAMPLE_PADDING, @@ -875,7 +824,7 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc if(BufferLoopItem) { /* Handle looping static source */ - const ALbuffer *Buffer{BufferListItem->front()}; + const ALbuffer *Buffer{BufferListItem->mBuffer}; const ALuint LoopStart{Buffer->LoopStart}; const ALuint LoopEnd{Buffer->LoopEnd}; if(DataPosInt >= LoopEnd) @@ -887,7 +836,7 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc else { /* Handle non-looping static source */ - if(DataPosInt >= BufferListItem->mMaxSamples) + if(DataPosInt >= BufferListItem->mSampleLen) { if LIKELY(vstate == ALvoice::Playing) vstate = ALvoice::Stopped; @@ -899,12 +848,12 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc else while(1) { /* Handle streaming source */ - if(BufferListItem->mMaxSamples > DataPosInt) + if(BufferListItem->mSampleLen > DataPosInt) break; - DataPosInt -= BufferListItem->mMaxSamples; + DataPosInt -= BufferListItem->mSampleLen; - buffers_done += BufferListItem->mNumBuffers; + ++buffers_done; BufferListItem = BufferListItem->mNext.load(std::memory_order_relaxed); if(!BufferListItem && !(BufferListItem=BufferLoopItem)) { |