#include #include namespace psemek::audio { namespace { struct loop_impl : stream { loop_impl(track_ptr dup, std::optional count) : dup_(std::move(dup)) , stream_(dup_->stream()) , count_(count) {} std::optional length() const override { if (count_) return (*stream_->length()) * (*count_); return std::nullopt; } std::size_t read(util::span samples) override { std::size_t count = 0; while (count < samples.size() && (!count_ || repeated_ < *count_)) { auto need = samples.size() - count; auto scount = stream_->read({samples.begin() + count, need}); count += scount; if (scount < need) { ++repeated_; stream_ = dup_->stream(); } } return count; } std::size_t played() const override { return stream_->played() + (*stream_->length()) * repeated_; } private: track_ptr dup_; stream_ptr stream_; std::optional count_; std::size_t repeated_ = 0; }; } stream_ptr loop(track_ptr track, std::optional count) { return std::make_shared(track, count); } stream_ptr loop(stream_ptr stream, std::optional count) { if (!stream->length()) return stream; return loop(make_duplicator(std::move(stream)), count); } }