diff --git a/libs/audio/include/psemek/audio/effect/concat.hpp b/libs/audio/include/psemek/audio/effect/concat.hpp new file mode 100644 index 00000000..47d97a55 --- /dev/null +++ b/libs/audio/include/psemek/audio/effect/concat.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +#include + +namespace psemek::audio +{ + + stream_ptr concat(std::vector streams); + +} diff --git a/libs/audio/source/effect/concat.cpp b/libs/audio/source/effect/concat.cpp new file mode 100644 index 00000000..75c1709c --- /dev/null +++ b/libs/audio/source/effect/concat.cpp @@ -0,0 +1,70 @@ +#include + +#include + +namespace psemek::audio +{ + + namespace + { + + struct concat_impl + : stream + { + concat_impl(std::vector streams) + : streams_(std::move(streams)) + { + length_ = 0; + for (auto const & stream : streams_) + { + if (auto length = stream->length()) + *length_ += *length; + else + { + length_ = std::nullopt; + break; + } + } + } + + std::optional length() const override + { + return length_; + } + + std::size_t read(float * data, std::size_t sample_count) override + { + std::size_t count = 0; + + for (; index_ != streams_.size(); ++index_) + { + count += streams_[index_]->read(data + count, sample_count - count); + if (count == sample_count) + break; + } + + played_.fetch_add(count); + + return count; + } + + std::size_t played() const override + { + return played_; + } + + private: + std::vector streams_; + std::optional length_; + std::atomic played_{0}; + std::size_t index_{0}; + }; + + } + + stream_ptr concat(std::vector streams) + { + return std::make_shared(std::move(streams)); + } + +}