#ifndef SPROUT_COMPOST_EFFECTS_REVERBED_HPP #define SPROUT_COMPOST_EFFECTS_REVERBED_HPP #include #include #include #include #include #include #include #include #include namespace sprout { namespace compost { // // reverb_outdirected_value // template struct reverb_outdirected_value { public: typedef Value value_type; typedef IntType int_type; private: value_type attenuation_; value_type delay_; std::size_t repeat_; int_type samples_per_sec_; private: template SPROUT_CONSTEXPR typename std::iterator_traits::value_type calc_1(Outdirected const& x, std::size_t i, typename Outdirected::index_type m) const { return m >= 0 ? sprout::math::pow(attenuation_, i) * x[m - x.index()] : 0 ; } template SPROUT_CONSTEXPR typename std::iterator_traits::value_type calc(Outdirected const& x, std::size_t i = 1) const { return i <= repeat_ ? calc_1(x, i, static_cast(x.index() - i * delay_ * samples_per_sec_)) + calc(x, i + 1) : 0 ; } public: SPROUT_CONSTEXPR reverb_outdirected_value( value_type const& attenuation, value_type const& delay, std::size_t repeat = 2, int_type samples_per_sec = 44100 ) : attenuation_(attenuation), delay_(delay), repeat_(repeat), samples_per_sec_(samples_per_sec) {} template SPROUT_CONSTEXPR typename std::iterator_traits::value_type operator()(Outdirected const& x) const { return *x + calc(x); } }; namespace effects { // // reverb_holder // template class reverb_holder { public: typedef T value_type; typedef IntType int_type; private: value_type attenuation_; value_type delay_; std::size_t repeat_; int_type samples_per_sec_; public: reverb_holder() = default; reverb_holder(reverb_holder const&) = default; SPROUT_CONSTEXPR reverb_holder( value_type const& attenuation, value_type const& delay, std::size_t repeat = 2, int_type samples_per_sec = 44100 ) : attenuation_(attenuation), delay_(delay), repeat_(repeat), samples_per_sec_(samples_per_sec) {} SPROUT_CONSTEXPR value_type const& attenuation() const { return attenuation_; } SPROUT_CONSTEXPR value_type const& delay() const { return delay_; } SPROUT_CONSTEXPR std::size_t const& repeat() const { return repeat_; } SPROUT_CONSTEXPR int_type const& samples_per_sec() const { return samples_per_sec_; } }; // // reverbed_forwarder // class reverbed_forwarder { public: template SPROUT_CONSTEXPR sprout::compost::effects::reverb_holder operator()(T const& attenuation, T const& delay, std::size_t repeat, IntType samples_per_sec) const { return sprout::compost::effects::reverb_holder(attenuation, delay, repeat, samples_per_sec); } template SPROUT_CONSTEXPR sprout::compost::effects::reverb_holder operator()(T const& attenuation, T const& delay, std::size_t repeat = 2) const { return sprout::compost::effects::reverb_holder(attenuation, delay, repeat); } }; // // reverbed // namespace { SPROUT_STATIC_CONSTEXPR sprout::compost::effects::reverbed_forwarder reverbed = {}; } // anonymous-namespace // // operator| // template inline SPROUT_CONSTEXPR auto operator|(Range&& lhs, sprout::compost::effects::reverb_holder const& rhs) -> decltype( sprout::forward(lhs) | sprout::adaptors::indexed | sprout::adaptors::outdirected | sprout::adaptors::transformed( sprout::compost::reverb_outdirected_value( rhs.attenuation(), rhs.delay(), rhs.repeat(), rhs.samples_per_sec() ) ) ) { return sprout::forward(lhs) | sprout::adaptors::indexed | sprout::adaptors::outdirected | sprout::adaptors::transformed( sprout::compost::reverb_outdirected_value( rhs.attenuation(), rhs.delay(), rhs.repeat(), rhs.samples_per_sec() ) ) ; } } // namespace effects using sprout::compost::effects::reverbed; } // namespace compost } // namespace sprout #endif // #ifndef SPROUT_COMPOST_EFFECTS_REVERBED_HPP