diff --git a/libs/audio/include/psemek/audio/effect/fade_in.hpp b/libs/audio/include/psemek/audio/effect/fade_in.hpp new file mode 100644 index 00000000..a41ca7d6 --- /dev/null +++ b/libs/audio/include/psemek/audio/effect/fade_in.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace psemek::audio +{ + + stream_ptr fade_in(stream_ptr stream, float length, float start = 0.f); + +} diff --git a/libs/audio/include/psemek/audio/effect/fade_out.hpp b/libs/audio/include/psemek/audio/effect/fade_out.hpp new file mode 100644 index 00000000..68fe8589 --- /dev/null +++ b/libs/audio/include/psemek/audio/effect/fade_out.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace psemek::audio +{ + + stream_ptr fade_out(stream_ptr stream, float length, float start = 0.f); + +} diff --git a/libs/audio/source/effect/fade_in.cpp b/libs/audio/source/effect/fade_in.cpp new file mode 100644 index 00000000..69a7b35e --- /dev/null +++ b/libs/audio/source/effect/fade_in.cpp @@ -0,0 +1,61 @@ +#include +#include + +#include + +namespace psemek::audio +{ + + namespace + { + + struct fade_in_impl + : stream + { + fade_in_impl(stream_ptr stream, float length, float start) + : stream_(std::move(stream)) + , length_(2 * std::round(length * frequency)) + , start_samples_(2 * std::round(start * frequency)) + {} + + 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); + + if (result <= start_samples_) + { + start_samples_ -= result; + } + else + { + for (std::size_t i = start_samples_; i < result; i += 2) + { + float m = static_cast(std::min(current_, length_)) / length_; + + data[i + 0] *= m; + data[i + 1] *= m; + + current_ += 2; + } + start_samples_ = 0; + } + + return result; + } + + private: + stream_ptr stream_; + std::size_t length_; + std::size_t current_ = 0; + std::size_t start_samples_; + }; + + } + + stream_ptr fade_in(stream_ptr stream, float length, float 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 new file mode 100644 index 00000000..5ce9806b --- /dev/null +++ b/libs/audio/source/effect/fade_out.cpp @@ -0,0 +1,63 @@ +#include +#include + +#include + +namespace psemek::audio +{ + + namespace + { + + struct fade_out_impl + : stream + { + fade_out_impl(stream_ptr stream, float length, float start) + : stream_(std::move(stream)) + , length_(2 * std::round(length * frequency)) + , start_samples_(2 * std::round(start * frequency)) + {} + + std::size_t read(float * data, std::size_t sample_count) override + { + if (current_ >= length_) + return 0; + + auto result = stream_->read(data, sample_count); + + if (result <= start_samples_) + { + start_samples_ -= result; + } + else + { + for (std::size_t i = start_samples_; i < result; i += 2) + { + float m = static_cast(length_ - std::min(current_, length_)) / length_; + + data[i + 0] *= m; + data[i + 1] *= m; + + current_ += 2; + } + start_samples_ = 0; + } + + return result; + } + + private: + stream_ptr stream_; + std::size_t length_; + std::size_t current_ = 0; + std::size_t start_samples_; + }; + + } + + stream_ptr fade_out(stream_ptr stream, float length, float start) + { + return std::make_shared(std::move(stream), length, start); + } + +}