aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--alc/backends/oboe.cpp49
1 files changed, 41 insertions, 8 deletions
diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp
index aefda974..38f048cb 100644
--- a/alc/backends/oboe.cpp
+++ b/alc/backends/oboe.cpp
@@ -193,6 +193,9 @@ struct OboeCapture final : public BackendBase {
oboe::ManagedStream mStream;
+ std::vector<al::byte> mSamples;
+ uint mLastAvail{0u};
+
void open(const char *name) override;
void start() override;
void stop() override;
@@ -289,6 +292,23 @@ void OboeCapture::start()
void OboeCapture::stop()
{
+ /* Capture any unread samples before stopping. Oboe drops whatever's left
+ * in the stream.
+ */
+ if(auto availres = mStream->getAvailableFrames())
+ {
+ const auto avail = std::max(static_cast<uint>(availres.value()), mLastAvail);
+ const size_t frame_size{static_cast<uint32_t>(mStream->getBytesPerFrame())};
+ const size_t pos{mSamples.size()};
+ mSamples.resize(pos + avail*frame_size);
+
+ auto result = mStream->read(&mSamples[pos], availres.value(), 0);
+ uint got{bool{result} ? static_cast<uint>(result.value()) : 0u};
+ if(got < avail)
+ std::fill_n(&mSamples[pos + got*frame_size], (avail-got)*frame_size, al::byte{});
+ mLastAvail = 0;
+ }
+
const oboe::Result result{mStream->stop()};
if(result != oboe::Result::OK)
throw al::backend_exception{al::backend_error::DeviceError, "Failed to stop stream: %s",
@@ -297,23 +317,36 @@ void OboeCapture::stop()
uint OboeCapture::availableSamples()
{
- auto result = mStream->getAvailableFrames();
- /* FIXME: This shouldn't report less samples than have been previously
- * reported and not captured.
+ /* Keep track of the max available frame count, to ensure it doesn't go
+ * backwards.
*/
- if(!result) return 0;
- return static_cast<uint>(result.value());
+ if(auto result = mStream->getAvailableFrames())
+ mLastAvail = std::max(static_cast<uint>(result.value()), mLastAvail);
+
+ const auto frame_size = static_cast<uint32_t>(mStream->getBytesPerFrame());
+ return static_cast<uint>(mSamples.size()/frame_size) + mLastAvail;
}
void OboeCapture::captureSamples(al::byte *buffer, uint samples)
{
+ const auto frame_size = static_cast<uint>(mStream->getBytesPerFrame());
+ if(const size_t storelen{mSamples.size()})
+ {
+ const auto instore = static_cast<uint>(storelen / frame_size);
+ const uint tocopy{std::min(samples, instore) * frame_size};
+ std::copy_n(mSamples.begin(), tocopy, buffer);
+ mSamples.erase(mSamples.begin(), mSamples.begin() + tocopy);
+
+ buffer += tocopy;
+ samples -= tocopy/frame_size;
+ if(!samples) return;
+ }
+
auto result = mStream->read(buffer, static_cast<int32_t>(samples), 0);
uint got{bool{result} ? static_cast<uint>(result.value()) : 0u};
if(got < samples)
- {
- auto frame_size = static_cast<uint>(mStream->getBytesPerFrame());
std::fill_n(buffer + got*frame_size, (samples-got)*frame_size, al::byte{});
- }
+ mLastAvail = std::max(mLastAvail, samples) - samples;
}
} // namespace