diff --git a/libs/audio/include/psemek/audio/duplicate.hpp b/libs/audio/include/psemek/audio/duplicate.hpp index 1b42bc5f..beef1b90 100644 --- a/libs/audio/include/psemek/audio/duplicate.hpp +++ b/libs/audio/include/psemek/audio/duplicate.hpp @@ -1,12 +1,21 @@ #pragma once #include +#include #include namespace psemek::audio { - std::pair duplicate(stream_ptr stream); + using duplicator = util::function; + + duplicator make_duplicator(stream_ptr stream); + + inline std::pair duplicate(stream_ptr stream) + { + auto dup = make_duplicator(std::move(stream)); + return {dup(), dup()}; + } } diff --git a/libs/audio/source/duplicate.cpp b/libs/audio/source/duplicate.cpp index c1964b59..e0bd5eb8 100644 --- a/libs/audio/source/duplicate.cpp +++ b/libs/audio/source/duplicate.cpp @@ -1,6 +1,7 @@ #include +#include -#include +#include namespace psemek::audio { @@ -8,61 +9,52 @@ namespace psemek::audio namespace { - struct duplicate_common - { - duplicate_common(stream_ptr stream) - : stream(std::move(stream)) - {} - - stream_ptr stream; - std::vector buffer; - std::size_t counter = 0; - std::size_t read = 0; - }; - struct duplicate_impl : stream { - duplicate_impl(std::shared_ptr common) - : common_(std::move(common)) + duplicate_impl(std::shared_ptr recorder) + : recorder_(std::move(recorder)) {} std::optional length() const override { - return common_->stream->length(); + return recorder_->stream()->length(); } std::size_t played() const override { - return common_->stream->played(); + return played_.load(); } std::size_t read(float * data, std::size_t sample_count) override { - if (counter_ == common_->counter) + auto buffer = recorder_->buffer(); + auto played = played_.load(); + if (buffer.size() < played + sample_count) { - ++common_->counter; - if (common_->buffer.size() < sample_count) - common_->buffer.resize(sample_count); - common_->read = common_->stream->read(common_->buffer.data(), sample_count); + recorder_->request(sample_count); + buffer = recorder_->buffer(); } - std::copy(common_->buffer.data(), common_->buffer.data() + common_->read, data); - ++counter_; - return common_->read; + auto count = std::min(sample_count, buffer.size() - played); + std::copy(buffer.data() + played, buffer.data() + played + count, data); + played_.fetch_add(count); + return count; } private: - std::shared_ptr common_; - std::size_t counter_ = 0; + std::shared_ptr recorder_; + std::atomic played_{0}; }; } - std::pair duplicate(stream_ptr stream) + duplicator make_duplicator(stream_ptr stream) { - auto common = std::make_shared(std::move(stream)); - return {std::make_shared(common), std::make_shared(common)}; + auto recorder = make_recorder(std::move(stream)); + return [recorder]{ + return std::make_shared(recorder); + }; } }