#pragma once #include #include #include "data/audioframe.h" #include "nodelib/basics.h" #include "audio/audioengine.h" using namespace Xybrid::Audio; namespace Xybrid::NodeLib { /// 12db Chamberlin State Variable Filter template class GenericSVFilter { public: /// Default oversampling level. Enough to mostly eliminate artifacting at high cutoff. static const constexpr int DEFAULT_OVERSAMP = 3; DT low = 0.0; DT high = 0.0; DT band = 0.0; DT notch = 0.0; GenericSVFilter() = default; ~GenericSVFilter() = default; // nothing used here should care about taking the raw approach inline GenericSVFilter
(const GenericSVFilter
& o) { std::memcpy(static_cast(this), static_cast(&o), sizeof(o)); } inline GenericSVFilter
& operator=(const GenericSVFilter
& o) { std::memcpy(static_cast(this), static_cast(&o), sizeof(o)); return *this; } void process(DT in, double cutoff, double resonance, int oversamp = DEFAULT_OVERSAMP) { if (oversamp <= 0) return; cutoff = std::max(cutoff, 1.0); resonance = std::max(resonance, 0.01); double f = 2.0 * std::sin(PI * cutoff / (audioEngine->curSampleRate() * oversamp)); double q = std::sqrt(1.0 - std::atan(std::sqrt(resonance)) * 2.0 / PI); double damp = std::sqrt(q); for (int i = 0; i < oversamp; i++) { low += band*f; high = in*damp - low - band*q; band += high*f; } notch = high+low; } inline void reset() { low = 0.0; high = 0.0; band = 0.0; notch = 0.0; } inline void normalize(double m) { if constexpr (std::is_arithmetic_v
) { low = std::clamp(low, -m, m); high = std::clamp(high, -m, m); band = std::clamp(band, -m, m); notch = std::clamp(notch, -m, m); } else { low = low.clamp(m); high = high.clamp(m); band = band.clamp(m); notch = notch.clamp(m); } } static inline double scaledResonance(double r) { return std::pow(10, r*5); } }; // explicit instantiation declarations to eliminate warnings extern template void Xybrid::NodeLib::GenericSVFilter::process(Data::AudioFrame, double, double, int); extern template void Xybrid::NodeLib::GenericSVFilter::process(double, double, double, int); /// 12db Chamberlin State Variable Filter typedef GenericSVFilter SVFilter; /// 12db Chamberlin State Variable Filter (mono version) typedef GenericSVFilter SVFilterM; }