diff --git a/libs/audio/include/psemek/audio/constants.hpp b/libs/audio/include/psemek/audio/constants.hpp index ac5ae90e..fcdbb013 100644 --- a/libs/audio/include/psemek/audio/constants.hpp +++ b/libs/audio/include/psemek/audio/constants.hpp @@ -1,9 +1,22 @@ #pragma once +#include +#include + namespace psemek::audio { constexpr int frequency = 44100; constexpr float inv_frequency = 1.f / frequency; + inline std::int64_t seconds_to_samples(float seconds) + { + return static_cast(2 * std::round(seconds * frequency)); + } + + inline float samples_to_seconds(std::int64_t samples) + { + return static_cast(samples) * 0.5f * inv_frequency; + } + } diff --git a/libs/audio/include/psemek/audio/duration.hpp b/libs/audio/include/psemek/audio/duration.hpp new file mode 100644 index 00000000..2bf22ca1 --- /dev/null +++ b/libs/audio/include/psemek/audio/duration.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include + +#include +#include + +namespace psemek::audio +{ + + struct duration + { + duration() + : samples_{0} + {} + + duration(std::int64_t samples) + : samples_{samples} + {} + + duration(std::size_t samples) + : samples_{samples} + {} + + duration(float seconds) + : samples_{seconds_to_samples(seconds)} + {} + + duration(duration const & other) = default; + + float seconds() const + { + return samples_to_seconds(samples_); + } + + std::int64_t samples() const + { + return samples_; + } + + duration & operator += (duration const & other) + { + samples_ += other.samples_; + return *this; + } + + duration & operator -= (duration const & other) + { + samples_ -= other.samples_; + return *this; + } + + friend duration operator + (duration const & d1, duration const & d2) + { + return duration{d1.samples() + d2.samples()}; + } + + friend duration operator - (duration const & d1, duration const & d2) + { + return duration{d1.samples() - d2.samples()}; + } + + private: + std::int64_t samples_; + }; + +} diff --git a/libs/audio/include/psemek/audio/effect/fade_in.hpp b/libs/audio/include/psemek/audio/effect/fade_in.hpp index a41ca7d6..fadc2358 100644 --- a/libs/audio/include/psemek/audio/effect/fade_in.hpp +++ b/libs/audio/include/psemek/audio/effect/fade_in.hpp @@ -1,10 +1,11 @@ #pragma once #include +#include namespace psemek::audio { - stream_ptr fade_in(stream_ptr stream, float length, float start = 0.f); + stream_ptr fade_in(stream_ptr stream, duration length, duration start = {}); } diff --git a/libs/audio/include/psemek/audio/effect/fade_out.hpp b/libs/audio/include/psemek/audio/effect/fade_out.hpp index 68fe8589..33920ed8 100644 --- a/libs/audio/include/psemek/audio/effect/fade_out.hpp +++ b/libs/audio/include/psemek/audio/effect/fade_out.hpp @@ -1,10 +1,11 @@ #pragma once #include +#include namespace psemek::audio { - stream_ptr fade_out(stream_ptr stream, float length, float start = 0.f); + stream_ptr fade_out(stream_ptr stream, duration length, duration start = {}); } diff --git a/libs/audio/source/effect/fade_in.cpp b/libs/audio/source/effect/fade_in.cpp index c1be8153..ab964526 100644 --- a/libs/audio/source/effect/fade_in.cpp +++ b/libs/audio/source/effect/fade_in.cpp @@ -12,10 +12,10 @@ namespace psemek::audio struct fade_in_impl : stream { - fade_in_impl(stream_ptr stream, float length, float start) + fade_in_impl(stream_ptr stream, duration length, duration start) : stream_(std::move(stream)) - , length_(2 * std::round(length * frequency)) - , start_samples_(2 * std::round(start * frequency)) + , length_(length) + , start_(start) {} std::optional length() const override @@ -31,24 +31,24 @@ namespace psemek::audio std::size_t read(float * data, std::size_t sample_count) override { auto const result = stream_->read(data, sample_count); - std::fill(data, data + std::min(result, start_samples_), 0.f); + std::fill(data, data + std::min(result, start_.samples()), 0.f); - if (result <= start_samples_) + if (result <= start_.samples()) { - start_samples_ -= result; + start_ -= result; } else { - for (std::size_t i = start_samples_; i < result; i += 2) + for (std::size_t i = start_.samples(); i < result; i += 2) { - float m = static_cast(std::min(current_, length_)) / length_; + float m = static_cast(std::min(current_, length_.samples())) / length_.samples(); data[i + 0] *= m; data[i + 1] *= m; current_ += 2; } - start_samples_ = 0; + start_ = duration{}; } return result; @@ -56,14 +56,14 @@ namespace psemek::audio private: stream_ptr stream_; - std::size_t length_; + duration length_; + duration start_; std::size_t current_ = 0; - std::size_t start_samples_; }; } - stream_ptr fade_in(stream_ptr stream, float length, float start) + stream_ptr fade_in(stream_ptr stream, duration length, duration start) { return std::make_shared(std::move(stream), length, start); } diff --git a/libs/audio/source/effect/fade_out.cpp b/libs/audio/source/effect/fade_out.cpp index 6d0e2b09..5f8be759 100644 --- a/libs/audio/source/effect/fade_out.cpp +++ b/libs/audio/source/effect/fade_out.cpp @@ -12,10 +12,10 @@ namespace psemek::audio struct fade_out_impl : stream { - fade_out_impl(stream_ptr stream, float length, float start) + fade_out_impl(stream_ptr stream, duration length, duration start) : stream_(std::move(stream)) - , length_(2 * std::round(length * frequency)) - , start_samples_(2 * std::round(start * frequency)) + , length_(length) + , start_(start) {} std::optional length() const override @@ -31,27 +31,27 @@ namespace psemek::audio std::size_t read(float * data, std::size_t sample_count) override { - if (current_ >= length_) + if (current_ >= length_.samples()) return 0; auto result = stream_->read(data, sample_count); - if (result <= start_samples_) + if (result <= start_.samples()) { - start_samples_ -= result; + start_ -= result; } else { - for (std::size_t i = start_samples_; i < result; i += 2) + for (std::size_t i = start_.samples(); i < result; i += 2) { - float m = static_cast(length_ - std::min(current_, length_)) / length_; + float m = static_cast(length_.samples() - std::min(current_, length_.samples())) / length_.samples(); data[i + 0] *= m; data[i + 1] *= m; current_ += 2; } - start_samples_ = 0; + start_ = {}; } return result; @@ -59,14 +59,14 @@ namespace psemek::audio private: stream_ptr stream_; - std::size_t length_; + duration length_; + duration start_; std::size_t current_ = 0; - std::size_t start_samples_; }; } - stream_ptr fade_out(stream_ptr stream, float length, float start) + stream_ptr fade_out(stream_ptr stream, duration length, duration start) { return std::make_shared(std::move(stream), length, start); }