GetSourceSampleOffset * * Gets the current read offset for the given Source, in 32.32 fixed-point * samples. The offset is relative to the start of the queue (not the start of * the current buffer). */
| 177 | * the current buffer). |
| 178 | */ |
| 179 | int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds *clocktime) |
| 180 | { |
| 181 | ALCdevice *device{context->mDevice.get()}; |
| 182 | const ALbufferlistitem *Current; |
| 183 | uint64_t readPos; |
| 184 | ALuint refcount; |
| 185 | ALvoice *voice; |
| 186 | |
| 187 | do { |
| 188 | Current = nullptr; |
| 189 | readPos = 0; |
| 190 | while(((refcount=device->MixCount.load(std::memory_order_acquire))&1)) |
| 191 | std::this_thread::yield(); |
| 192 | *clocktime = GetDeviceClockTime(device); |
| 193 | |
| 194 | voice = GetSourceVoice(Source, context); |
| 195 | if(voice) |
| 196 | { |
| 197 | Current = voice->mCurrentBuffer.load(std::memory_order_relaxed); |
| 198 | |
| 199 | readPos = uint64_t{voice->mPosition.load(std::memory_order_relaxed)} << 32; |
| 200 | readPos |= uint64_t{voice->mPositionFrac.load(std::memory_order_relaxed)} << |
| 201 | (32-FRACTIONBITS); |
| 202 | } |
| 203 | std::atomic_thread_fence(std::memory_order_acquire); |
| 204 | } while(refcount != device->MixCount.load(std::memory_order_relaxed)); |
| 205 | |
| 206 | if(voice) |
| 207 | { |
| 208 | const ALbufferlistitem *BufferList{Source->queue}; |
| 209 | while(BufferList && BufferList != Current) |
| 210 | { |
| 211 | readPos += uint64_t{BufferList->mSampleLen} << 32; |
| 212 | BufferList = BufferList->mNext.load(std::memory_order_relaxed); |
| 213 | } |
| 214 | readPos = minu64(readPos, 0x7fffffffffffffff_u64); |
| 215 | } |
| 216 | |
| 217 | return static_cast<int64_t>(readPos); |
| 218 | } |
| 219 | |
| 220 | /* GetSourceSecOffset |
| 221 | * |
no test coverage detected