/*============================================================================= Copyright (c) 2011-2017 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_COMPOST_EFFECTS_VIBRATO_HPP #define SPROUT_COMPOST_EFFECTS_VIBRATO_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { namespace compost { // // vibrato_outdirected_value // template struct vibrato_outdirected_value { public: typedef Value value_type; typedef IntType int_type; private: value_type d_; value_type depth_; value_type rate_; int_type samples_per_sec_; private: template SPROUT_CONSTEXPR typename std::iterator_traits::value_type calc_2(Outdirected const& x, typename Outdirected::index_type m, value_type const& delta) const { return m >= 0 && (m + 1 < x.base().get() || x.base().get() < 0) ? delta * x[m + 1 - x.index()] + (1 - delta) * x[m - x.index()] : 0 ; } template SPROUT_CONSTEXPR typename std::iterator_traits::value_type calc_1(Outdirected const& x, value_type const& t) const { return calc_2(x, static_cast(t), t - static_cast(t)); } template SPROUT_CONSTEXPR typename std::iterator_traits::value_type calc(Outdirected const& x, value_type const& tau) const { return calc_1(x, x.index() - tau); } public: SPROUT_CONSTEXPR vibrato_outdirected_value( value_type const& d, value_type const& depth, value_type const& rate, int_type samples_per_sec = 44100 ) : d_(d), depth_(depth), rate_(rate), samples_per_sec_(samples_per_sec) {} template SPROUT_CONSTEXPR typename std::iterator_traits::value_type operator()(Outdirected const& x) const { return calc(x, d_ + depth_ * sprout::sin(sprout::math::two_pi() * rate_ * x.index() / samples_per_sec_)); } }; namespace effects { // // vibrato_holder // template class vibrato_holder { public: typedef T value_type; typedef IntType int_type; private: value_type d_; value_type depth_; value_type rate_; int_type samples_per_sec_; public: SPROUT_CONSTEXPR vibrato_holder() SPROUT_DEFAULTED_DEFAULT_CONSTRUCTOR_DECL vibrato_holder(vibrato_holder const&) = default; SPROUT_CONSTEXPR vibrato_holder( value_type const& d, value_type const& depth, value_type const& rate, int_type samples_per_sec = 44100 ) : d_(d), depth_(depth), rate_(rate), samples_per_sec_(samples_per_sec) {} SPROUT_CONSTEXPR value_type const& d() const { return d_; } SPROUT_CONSTEXPR value_type const& depth() const { return depth_; } SPROUT_CONSTEXPR value_type const& rate() const { return rate_; } SPROUT_CONSTEXPR int_type const& samples_per_sec() const { return samples_per_sec_; } }; // // vibrato_forwarder // class vibrato_forwarder { public: template SPROUT_CONSTEXPR sprout::compost::effects::vibrato_holder operator()(T const& d, T const& depth, T const& rate, IntType samples_per_sec) const { return sprout::compost::effects::vibrato_holder(d, depth, rate, samples_per_sec); } template SPROUT_CONSTEXPR sprout::compost::effects::vibrato_holder operator()(T const& d, T const& depth, T const& rate) const { return sprout::compost::effects::vibrato_holder(d, depth, rate); } }; // // vibrato // namespace { SPROUT_STATIC_CONSTEXPR sprout::compost::effects::vibrato_forwarder vibrato = {}; } // anonymous-namespace // // operator| // template inline SPROUT_CONSTEXPR auto operator|(Range&& lhs, sprout::compost::effects::vibrato_holder const& rhs) -> decltype( SPROUT_FORWARD(Range, lhs) | sprout::adaptors::valued(sprout::size(SPROUT_FORWARD(Range, lhs))) | sprout::adaptors::indexed | sprout::adaptors::outdirected | sprout::adaptors::transformed( sprout::compost::vibrato_outdirected_value( rhs.d(), rhs.depth(), rhs.rate(), rhs.samples_per_sec() ) ) ) { return SPROUT_FORWARD(Range, lhs) | sprout::adaptors::valued(sprout::size(SPROUT_FORWARD(Range, lhs))) | sprout::adaptors::indexed | sprout::adaptors::outdirected | sprout::adaptors::transformed( sprout::compost::vibrato_outdirected_value( rhs.d(), rhs.depth(), rhs.rate(), rhs.samples_per_sec() ) ) ; } } // namespace effects using sprout::compost::effects::vibrato; } // namespace compost } // namespace sprout #endif // #ifndef SPROUT_COMPOST_EFFECTS_VIBRATO_HPP