diff --git a/libs/audio/include/psemek/audio/engine.hpp b/libs/audio/include/psemek/audio/engine.hpp index 2731262f..ec4b3cf6 100644 --- a/libs/audio/include/psemek/audio/engine.hpp +++ b/libs/audio/include/psemek/audio/engine.hpp @@ -7,6 +7,8 @@ #include #include +#include + #include #include #include @@ -19,8 +21,8 @@ namespace psemek::audio engine(); ~engine(); - track_ptr load(float const * data, std::size_t sample_count, bool copy = true); - track_ptr load(util::span data, bool copy = true); + track_ptr load_raw(float const * data, std::size_t sample_count, bool copy = true); + track_ptr load_raw(util::span data, bool copy = true); channel_ptr output(); diff --git a/libs/audio/source/engine.cpp b/libs/audio/source/engine.cpp index 923dff72..3fc4e61d 100644 --- a/libs/audio/source/engine.cpp +++ b/libs/audio/source/engine.cpp @@ -15,6 +15,70 @@ namespace psemek::audio { + namespace + { + + struct track_data + { + util::span samples; + std::vector storage; + }; + + struct track_stream_impl + : stream + { + track_stream_impl(std::shared_ptr data) + : data_(std::move(data)) + {} + + std::optional length() const override + { + return data_->samples.size(); + } + + std::size_t read(float * data, std::size_t sample_count) override + { + auto played = played_.load(); + + std::size_t result = std::min(sample_count, data_->samples.size() - played); + std::copy(data_->samples.data() + played, data_->samples.data() + played + result, data); + played_.fetch_add(result); + return result; + } + + std::size_t played() const override + { + return played_.load(); + } + + private: + std::shared_ptr data_; + std::atomic played_{0}; + }; + + struct track_impl + : track + { + track_impl(std::shared_ptr data) + : data_(std::move(data)) + {} + + stream_ptr stream() const override + { + return std::make_shared(data_); + } + + std::size_t length() const override + { + return data_->samples.size(); + } + + private: + std::shared_ptr data_; + }; + + } + struct engine::impl { std::shared_ptr sdl_init; @@ -90,21 +154,26 @@ namespace psemek::audio engine::~engine() = default; - track_ptr engine::load(float const * data, std::size_t sample_count, bool copy) + track_ptr engine::load_raw(float const * data, std::size_t sample_count, bool copy) { if ((sample_count % 2) != 0) throw std::runtime_error("bad sample count"); - (void)data; - (void)sample_count; - (void)copy; + auto tdata = std::make_shared(); + if (copy) + { + tdata->storage.assign(data, data + sample_count); + tdata->samples = tdata->storage; + } + else + tdata->samples = {data, data + sample_count}; - return nullptr; + return std::make_shared(std::move(tdata)); } - track_ptr engine::load(util::span data, bool copy) + track_ptr engine::load_raw(util::span data, bool copy) { - return load(data.data(), data.size(), copy); + return load_raw(data.data(), data.size(), copy); } channel_ptr engine::output()