From 855a8c0cd9c79d3e708d037811b04a821f95a5bc Mon Sep 17 00:00:00 2001 From: Chris Robinson <chris.kcat@gmail.com> Date: Fri, 15 Jan 2021 18:18:07 -0800 Subject: Don't assume the ring buffer's read vector is the next writable space This is untrue since the ring buffer leaves one element unwritten, so there's one extra element to be written once a readable element is read. --- alc/backends/opensl.cpp | 66 +++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 30 deletions(-) (limited to 'alc/backends/opensl.cpp') diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index 8d966fca..f6e7fddb 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -868,30 +868,18 @@ void OpenSLCapture::stop() void OpenSLCapture::captureSamples(al::byte *buffer, uint samples) { - SLAndroidSimpleBufferQueueItf bufferQueue{}; - if LIKELY(mDevice->Connected.load(std::memory_order_acquire)) - { - const SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, - &bufferQueue)}; - PRINTERR(result, "recordObj->GetInterface"); - if UNLIKELY(SL_RESULT_SUCCESS != result) - { - mDevice->handleDisconnect("Failed to get capture buffer queue: 0x%08x", result); - bufferQueue = nullptr; - } - } - const uint update_size{mDevice->UpdateSize}; const uint chunk_size{update_size * mFrameSize}; /* Read the desired samples from the ring buffer then advance its read * pointer. */ - auto data = mRing->getReadVector(); + auto rdata = mRing->getReadVector(); for(uint i{0};i < samples;) { const uint rem{minu(samples - i, update_size - mSplOffset)}; - std::copy_n(data.first.buf + mSplOffset*mFrameSize, rem*mFrameSize, buffer + i*mFrameSize); + std::copy_n(rdata.first.buf + mSplOffset*mFrameSize, rem*mFrameSize, + buffer + i*mFrameSize); mSplOffset += rem; if(mSplOffset == update_size) @@ -900,26 +888,44 @@ void OpenSLCapture::captureSamples(al::byte *buffer, uint samples) mSplOffset = 0; mRing->readAdvance(1); - if LIKELY(bufferQueue) - { - const SLresult result{VCALL(bufferQueue,Enqueue)(data.first.buf, chunk_size)}; - PRINTERR(result, "bufferQueue->Enqueue"); - if UNLIKELY(SL_RESULT_SUCCESS != result) - { - mDevice->handleDisconnect("Failed to update capture buffer: 0x%08x", result); - bufferQueue = nullptr; - } - } - - data.first.len--; - if(!data.first.len) - data.first = data.second; + rdata.first.len -= 1; + if(!rdata.first.len) + rdata.first = rdata.second; else - data.first.buf += chunk_size; + rdata.first.buf += chunk_size; } i += rem; } + + SLAndroidSimpleBufferQueueItf bufferQueue{}; + if LIKELY(mDevice->Connected.load(std::memory_order_acquire)) + { + const SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &bufferQueue)}; + PRINTERR(result, "recordObj->GetInterface"); + if UNLIKELY(SL_RESULT_SUCCESS != result) + { + mDevice->handleDisconnect("Failed to get capture buffer queue: 0x%08x", result); + bufferQueue = nullptr; + } + } + + if LIKELY(bufferQueue) + { + SLresult result{SL_RESULT_SUCCESS}; + auto wdata = mRing->getWriteVector(); + for(size_t i{0u};i < wdata.first.len && SL_RESULT_SUCCESS == result;i++) + { + result = VCALL(bufferQueue,Enqueue)(wdata.first.buf + chunk_size*i, chunk_size); + PRINTERR(result, "bufferQueue->Enqueue"); + } + for(size_t i{0u};i < wdata.second.len && SL_RESULT_SUCCESS == result;i++) + { + result = VCALL(bufferQueue,Enqueue)(wdata.second.buf + chunk_size*i, chunk_size); + PRINTERR(result, "bufferQueue->Enqueue"); + } + } } uint OpenSLCapture::availableSamples() -- cgit v1.2.3