diff options
Diffstat (limited to 'al')
-rw-r--r-- | al/source.cpp | 97 |
1 files changed, 40 insertions, 57 deletions
diff --git a/al/source.cpp b/al/source.cpp index 9bae27a5..1b5aa851 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -377,96 +377,79 @@ ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) } -/* GetSampleOffset +struct VoicePos { + ALuint pos, frac; + ALbufferlistitem *bufferitem; +}; + +/** + * GetSampleOffset * - * Retrieves the sample offset into the Source's queue (from the Sample, Byte - * or Second offset supplied by the application). This takes into account the - * fact that the buffer format may have been modifed since. + * Retrieves the voice position, fixed-point fraction, and bufferlist item + * using the source's stored offset and offset type. If the source has no + * stored offset, or the offset is out of range, returns an empty optional. */ -bool GetSampleOffset(ALsource *Source, ALuint *offset, ALuint *frac) +al::optional<VoicePos> GetSampleOffset(ALsource *Source) { - const ALbuffer *BufferFmt{nullptr}; - const ALbufferlistitem *BufferList; - + al::optional<VoicePos> ret; + /* Find the first valid Buffer in the Queue */ - BufferList = Source->queue; - while(BufferList && !BufferFmt) + const ALbuffer *BufferFmt{nullptr}; + ALbufferlistitem *BufferList{Source->queue}; + while(BufferList) { - BufferFmt = BufferList->mBuffer; + if((BufferFmt=BufferList->mBuffer) != nullptr) break; BufferList = BufferList->mNext.load(std::memory_order_relaxed); } - if(!BufferFmt) + if(!BufferList) { Source->OffsetType = AL_NONE; Source->Offset = 0.0; - return false; + return ret; } + /* Get sample frame offset */ + ALuint offset{0u}, frac{0u}; ALdouble dbloff, dblfrac; switch(Source->OffsetType) { case AL_BYTE_OFFSET: /* Determine the ByteOffset (and ensure it is block aligned) */ - *offset = static_cast<ALuint>(Source->Offset); + offset = static_cast<ALuint>(Source->Offset); if(BufferFmt->OriginalType == UserFmtIMA4) { - ALsizei align = (BufferFmt->OriginalAlign-1)/2 + 4; - *offset /= align * ChannelsFromFmt(BufferFmt->mFmtChannels); - *offset *= BufferFmt->OriginalAlign; + const ALsizei align{(BufferFmt->OriginalAlign-1)/2 + 4}; + offset /= align * ChannelsFromFmt(BufferFmt->mFmtChannels); + offset *= BufferFmt->OriginalAlign; } else if(BufferFmt->OriginalType == UserFmtMSADPCM) { - ALsizei align = (BufferFmt->OriginalAlign-2)/2 + 7; - *offset /= align * ChannelsFromFmt(BufferFmt->mFmtChannels); - *offset *= BufferFmt->OriginalAlign; + const ALsizei align{(BufferFmt->OriginalAlign-2)/2 + 7}; + offset /= align * ChannelsFromFmt(BufferFmt->mFmtChannels); + offset *= BufferFmt->OriginalAlign; } else - *offset /= FrameSizeFromFmt(BufferFmt->mFmtChannels, BufferFmt->mFmtType); - *frac = 0; + offset /= FrameSizeFromFmt(BufferFmt->mFmtChannels, BufferFmt->mFmtType); + frac = 0; break; case AL_SAMPLE_OFFSET: - dblfrac = modf(Source->Offset, &dbloff); - *offset = static_cast<ALuint>(mind(dbloff, std::numeric_limits<ALuint>::max())); - *frac = static_cast<ALuint>(mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0)); + dblfrac = std::modf(Source->Offset, &dbloff); + offset = static_cast<ALuint>(mind(dbloff, std::numeric_limits<ALuint>::max())); + frac = static_cast<ALuint>(mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0)); break; case AL_SEC_OFFSET: - dblfrac = modf(Source->Offset*BufferFmt->Frequency, &dbloff); - *offset = static_cast<ALuint>(mind(dbloff, std::numeric_limits<ALuint>::max())); - *frac = static_cast<ALuint>(mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0)); + dblfrac = std::modf(Source->Offset*BufferFmt->Frequency, &dbloff); + offset = static_cast<ALuint>(mind(dbloff, std::numeric_limits<ALuint>::max())); + frac = static_cast<ALuint>(mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0)); break; } Source->OffsetType = AL_NONE; Source->Offset = 0.0; - return true; -} - - -struct VoicePos { - ALuint pos, frac; - ALbufferlistitem *bufferitem; -}; - -/** - * CalcOffset - * - * Calculates the voice position, fixed-point fraction, and bufferlist item - * using the source's stored offset. If the source has no stored offset, or the - * offset is out of range, returns an empty optional. - */ -al::optional<VoicePos> CalcOffset(ALsource *Source) -{ - al::optional<VoicePos> ret; - - /* Get sample frame offset */ - ALuint offset{0u}, frac{0u}; - if(!GetSampleOffset(Source, &offset, &frac)) - return ret; - + /* Find the bufferlist item this offset belongs to. */ ALuint totalBufferLen{0u}; - ALbufferlistitem *BufferList{Source->queue}; while(BufferList && totalBufferLen <= offset) { if(BufferList->mSampleLen > offset-totalBufferLen) @@ -1021,7 +1004,7 @@ bool SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a */ if(ALvoice *voice{GetSourceVoice(Source, Context)}) { - auto vpos = CalcOffset(Source); + auto vpos = GetSampleOffset(Source); if(!vpos) SETERR_RETURN(Context, AL_INVALID_VALUE, false, "Invalid offset"); voice->mPosition.store(vpos->pos, std::memory_order_relaxed); @@ -1240,7 +1223,7 @@ bool SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a BackendLockGuard _{*device->Backend}; if(ALvoice *voice{GetSourceVoice(Source, Context)}) { - auto vpos = CalcOffset(Source); + 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); @@ -2781,7 +2764,7 @@ START_API_FUNC voice->mPosition.store(0u, std::memory_order_relaxed); voice->mPositionFrac.store(0, std::memory_order_relaxed); bool start_fading{false}; - if(auto vpos = CalcOffset(source)) + if(auto vpos = GetSampleOffset(source)) { start_fading = vpos->pos != 0 || vpos->frac != 0 || vpos->bufferitem != BufferList; voice->mPosition.store(vpos->pos, std::memory_order_relaxed); |