diff --git a/sprout/compost/effects.hpp b/sprout/compost/effects.hpp index a180ae5a..14af34a4 100644 --- a/sprout/compost/effects.hpp +++ b/sprout/compost/effects.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/sprout/compost/effects/chorus.hpp b/sprout/compost/effects/chorus.hpp new file mode 100644 index 00000000..7de7f4bf --- /dev/null +++ b/sprout/compost/effects/chorus.hpp @@ -0,0 +1,156 @@ +#ifndef SPROUT_COMPOST_EFFECTS_CHORUS_HPP +#define SPROUT_COMPOST_EFFECTS_CHORUS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace compost { + // + // chorus_outdirected_value + // + template + struct chorus_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 *x + (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& tau, 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, tau, x.index() - tau); + } + public: + SPROUT_CONSTEXPR chorus_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::math::sin(2 * sprout::math::pi() * rate_ * x.index() / samples_per_sec_)); + } + }; + + namespace effects { + // + // chorus_holder + // + template + class chorus_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: + chorus_holder() = default; + chorus_holder(chorus_holder const&) = default; + SPROUT_CONSTEXPR chorus_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_; + } + }; + + // + // chorus_forwarder + // + class chorus_forwarder { + public: + template + SPROUT_CONSTEXPR sprout::compost::effects::chorus_holder + operator()(T const& d, T const& depth, T const& rate, IntType samples_per_sec) { + return sprout::compost::effects::chorus_holder(d, depth, rate, samples_per_sec); + } + template + SPROUT_CONSTEXPR sprout::compost::effects::chorus_holder + operator()(T const& d, T const& depth, T const& rate) { + return sprout::compost::effects::chorus_holder(d, depth, rate); + } + }; + + // + // chorus + // + namespace { + SPROUT_STATIC_CONSTEXPR sprout::compost::effects::chorus_forwarder chorus{}; + } // anonymous-namespace + + // + // operator| + // + template + inline SPROUT_CONSTEXPR auto + operator|(Range&& lhs, sprout::compost::effects::chorus_holder const& rhs) + -> decltype( + sprout::forward(lhs) + | sprout::adaptors::valued(sprout::size(sprout::forward(lhs))) + | sprout::adaptors::indexed | sprout::adaptors::outdirected + | sprout::adaptors::transformed( + sprout::compost::chorus_outdirected_value( + rhs.d(), rhs.depth(), rhs.rate(), rhs.samples_per_sec() + ) + ) + ) + { + return sprout::forward(lhs) + | sprout::adaptors::valued(sprout::size(sprout::forward(lhs))) + | sprout::adaptors::indexed | sprout::adaptors::outdirected + | sprout::adaptors::transformed( + sprout::compost::chorus_outdirected_value( + rhs.d(), rhs.depth(), rhs.rate(), rhs.samples_per_sec() + ) + ) + ; + } + } // namespace effects + } // namespace compost +} // namespace sprout + +#endif // #ifndef SPROUT_COMPOST_EFFECTS_CHORUS_HPP diff --git a/sprout/compost/effects/vibrato.hpp b/sprout/compost/effects/vibrato.hpp index 7a90a112..f9e9277c 100644 --- a/sprout/compost/effects/vibrato.hpp +++ b/sprout/compost/effects/vibrato.hpp @@ -33,7 +33,7 @@ namespace sprout { 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()] - : *x + : 0 ; } template diff --git a/sprout/config/compiler/clang.hpp b/sprout/config/compiler/clang.hpp index 322741a7..72f6cc4b 100644 --- a/sprout/config/compiler/clang.hpp +++ b/sprout/config/compiler/clang.hpp @@ -21,8 +21,8 @@ # define SPROUT_NO_DELEGATING_CONSTRUCTORS #endif -#if (__has_feature(cxx_constexpr) && (__GNUC__ >= 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) -# define SPROUT_HAS_CONSTEXPR_CMATH_FUNCTION -#endif +//#if (__has_feature(cxx_constexpr) && (__GNUC__ >= 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) +//# define SPROUT_HAS_CONSTEXPR_CMATH_FUNCTION +//#endif #endif // #ifndef SPROUT_CONFIG_COMPILER_CLANG_HPP