diff --git a/libs/audio/include/psemek/audio/stream.hpp b/libs/audio/include/psemek/audio/stream.hpp index 323d6d24..dbb5f65f 100644 --- a/libs/audio/include/psemek/audio/stream.hpp +++ b/libs/audio/include/psemek/audio/stream.hpp @@ -2,13 +2,18 @@ #include #include +#include namespace psemek::audio { struct stream { + // The length of the stream in samples, or nullopt if the stream is infinite + virtual std::optional length() const = 0; + // Return value less than sample count means end of stream + // Must be called from mixing thread virtual std::size_t read(float * data, std::size_t sample_count) = 0; virtual ~stream() {} diff --git a/libs/audio/include/psemek/audio/wave/generator.hpp b/libs/audio/include/psemek/audio/wave/generator.hpp index 25717e6e..04c59cdc 100644 --- a/libs/audio/include/psemek/audio/wave/generator.hpp +++ b/libs/audio/include/psemek/audio/wave/generator.hpp @@ -14,6 +14,11 @@ namespace psemek::audio : func_(std::move(func)) {} + std::optional length() const override + { + return std::nullopt; + } + std::size_t read(float * data, std::size_t sample_count) override { auto end = data + sample_count; diff --git a/libs/audio/source/duplicate.cpp b/libs/audio/source/duplicate.cpp index 79da6586..6bdeb0bd 100644 --- a/libs/audio/source/duplicate.cpp +++ b/libs/audio/source/duplicate.cpp @@ -27,6 +27,11 @@ namespace psemek::audio : common_(std::move(common)) {} + std::optional length() const override + { + return common_->stream->length(); + } + std::size_t read(float * data, std::size_t sample_count) override { if (counter_ == common_->counter) diff --git a/libs/audio/source/effect/fade_in.cpp b/libs/audio/source/effect/fade_in.cpp index 69a7b35e..ba4c0700 100644 --- a/libs/audio/source/effect/fade_in.cpp +++ b/libs/audio/source/effect/fade_in.cpp @@ -18,6 +18,11 @@ namespace psemek::audio , start_samples_(2 * std::round(start * frequency)) {} + std::optional length() const override + { + return stream_->length(); + } + std::size_t read(float * data, std::size_t sample_count) override { auto const result = stream_->read(data, sample_count); diff --git a/libs/audio/source/effect/fade_out.cpp b/libs/audio/source/effect/fade_out.cpp index 5ce9806b..9f7b6266 100644 --- a/libs/audio/source/effect/fade_out.cpp +++ b/libs/audio/source/effect/fade_out.cpp @@ -18,6 +18,12 @@ namespace psemek::audio , start_samples_(2 * std::round(start * frequency)) {} + std::optional length() const override + { + // TODO: compute fade_out length using the number of samples already played + return stream_->length(); + } + std::size_t read(float * data, std::size_t sample_count) override { if (current_ >= length_) diff --git a/libs/audio/source/effect/volume.cpp b/libs/audio/source/effect/volume.cpp index 11f9855b..28a4584b 100644 --- a/libs/audio/source/effect/volume.cpp +++ b/libs/audio/source/effect/volume.cpp @@ -21,6 +21,11 @@ namespace psemek::audio float smoothness() const override { return base_.smoothness(); } float smoothness(float value) override { return base_.smoothness(value); } + std::optional length() const override + { + return stream_->length(); + } + std::size_t read(float * data, std::size_t sample_count) override { auto result = stream_->read(data, sample_count); diff --git a/libs/audio/source/mixer.cpp b/libs/audio/source/mixer.cpp index af4ac4fe..460d4466 100644 --- a/libs/audio/source/mixer.cpp +++ b/libs/audio/source/mixer.cpp @@ -18,6 +18,11 @@ namespace psemek::audio std::size_t read(float * data, std::size_t sample_count) override; + std::optional length() const override + { + return std::nullopt; + } + private: std::vector channels_; std::vector alive_channels_; diff --git a/libs/audio/source/stereo.cpp b/libs/audio/source/stereo.cpp index 6ea32820..b5c0b0c1 100644 --- a/libs/audio/source/stereo.cpp +++ b/libs/audio/source/stereo.cpp @@ -16,6 +16,19 @@ namespace psemek::audio , right_(std::move(right)) {} + std::optional length() const override + { + auto left = left_->length(); + auto right = right_->length(); + + if (left && right) + return std::min(*left, *right); + else if (left) + return left; + else + return right; + } + std::size_t read(float * data, std::size_t sample_count) override { if (buffer_.size() < sample_count) diff --git a/libs/audio/source/wave/silence.cpp b/libs/audio/source/wave/silence.cpp index 9bb36508..7d3c1d3d 100644 --- a/libs/audio/source/wave/silence.cpp +++ b/libs/audio/source/wave/silence.cpp @@ -14,6 +14,11 @@ namespace psemek::audio std::fill(data, data + sample_count, 0.f); return sample_count; } + + std::optional length() const override + { + return std::nullopt; + } }; }