#include #include #include namespace psemek::audio { namespace { struct distortion_impl : distortion_control { distortion_impl(stream_ptr stream, float strength) : stream_(std::move(stream)) , strength_(strength) {} float strength() const override { return strength_.load(); } float strength(float value) override { return strength_.exchange(value); } std::optional length() const override { return stream_->length(); } std::size_t read(util::span samples) override { auto count = stream_->read(samples); float strength = strength_.load(); for (std::size_t i = 0; i < count; ++i) { samples[i] = std::tanh(strength * samples[i]); } return count; } std::size_t played() const override { return stream_->played(); } private: stream_ptr stream_; std::atomic strength_; }; } stream_ptr distortion(stream_ptr stream, float strength) { return std::make_shared(std::move(stream), strength); } }