From acc2fd486e783990194261c5398a5cb4e22535bf Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 6 Oct 2022 15:55:14 +0300 Subject: [PATCH] Implement looping effect --- .../include/psemek/audio/effect/loop.hpp | 10 +++ libs/audio/source/effect/loop.cpp | 64 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 libs/audio/include/psemek/audio/effect/loop.hpp create mode 100644 libs/audio/source/effect/loop.cpp diff --git a/libs/audio/include/psemek/audio/effect/loop.hpp b/libs/audio/include/psemek/audio/effect/loop.hpp new file mode 100644 index 00000000..c3a0347c --- /dev/null +++ b/libs/audio/include/psemek/audio/effect/loop.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace psemek::audio +{ + + stream_ptr loop(stream_ptr stream, std::optional count = {}); + +} diff --git a/libs/audio/source/effect/loop.cpp b/libs/audio/source/effect/loop.cpp new file mode 100644 index 00000000..3ae970fe --- /dev/null +++ b/libs/audio/source/effect/loop.cpp @@ -0,0 +1,64 @@ +#include +#include + +namespace psemek::audio +{ + + namespace + { + + struct loop_impl + : stream + { + loop_impl(duplicator dup, std::optional count) + : dup_(std::move(dup)) + , stream_(dup_()) + , count_(count) + {} + + std::optional length() const override + { + if (count_) + return (*stream_->length()) * (*count_); + return std::nullopt; + } + + std::size_t read(float * data, std::size_t sample_count) override + { + std::size_t result = 0; + while (result < sample_count && (!count_ || repeated_ < *count_)) + { + auto need = sample_count - result; + auto count = stream_->read(data + result, need); + result += count; + if (count < need) + { + ++repeated_; + stream_ = dup_(); + } + } + return result; + } + + std::size_t played() const override + { + return stream_->played() + (*stream_->length()) * repeated_; + } + + private: + duplicator dup_; + stream_ptr stream_; + std::optional count_; + std::size_t repeated_ = 0; + }; + + } + + stream_ptr loop(stream_ptr stream, std::optional count) + { + if (!stream->length()) + return stream; + return std::make_shared(make_duplicator(std::move(stream)), count); + } + +}