template wizardry resulting in a mono version of SVFilter for synth use
parent
acbca4ae0b
commit
a28d6e48b6
4
notes
4
notes
|
@ -35,9 +35,7 @@ TODO {
|
||||||
about-license info
|
about-license info
|
||||||
}
|
}
|
||||||
|
|
||||||
- fix overrun-by-1 on sample preview
|
- templatize svfilter and have mono version for synth use
|
||||||
|
|
||||||
templatize svfilter and have mono version for synth use
|
|
||||||
|
|
||||||
revert-to-saved menu action
|
revert-to-saved menu action
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,15 @@
|
||||||
#include "audio/audioengine.h"
|
#include "audio/audioengine.h"
|
||||||
|
|
||||||
using Xybrid::NodeLib::SVFilter;
|
using Xybrid::NodeLib::SVFilter;
|
||||||
|
using Xybrid::NodeLib::GenericSVFilter;
|
||||||
using Xybrid::Data::AudioFrame;
|
using Xybrid::Data::AudioFrame;
|
||||||
using namespace Xybrid::Audio;
|
using namespace Xybrid::Audio;
|
||||||
|
|
||||||
void SVFilter::process(AudioFrame in, double cutoff, double resonance, int ovs) {
|
template class Xybrid::NodeLib::GenericSVFilter<AudioFrame>;
|
||||||
|
template class Xybrid::NodeLib::GenericSVFilter<double>;
|
||||||
|
|
||||||
|
template<typename DT>
|
||||||
|
void GenericSVFilter<DT>::process(DT in, double cutoff, double resonance, int ovs) {
|
||||||
if (ovs <= 0) return;
|
if (ovs <= 0) return;
|
||||||
cutoff = std::max(cutoff, 1.0);
|
cutoff = std::max(cutoff, 1.0);
|
||||||
resonance = std::max(resonance, 0.01);
|
resonance = std::max(resonance, 0.01);
|
||||||
|
|
|
@ -7,32 +7,44 @@
|
||||||
|
|
||||||
namespace Xybrid::NodeLib {
|
namespace Xybrid::NodeLib {
|
||||||
/// 12db Chamberlin State Variable Filter
|
/// 12db Chamberlin State Variable Filter
|
||||||
class SVFilter {
|
template<typename DT> class GenericSVFilter {
|
||||||
//
|
|
||||||
public:
|
public:
|
||||||
/// Default oversampling level. Enough to mostly eliminate artifacting at high cutoff.
|
/// Default oversampling level. Enough to mostly eliminate artifacting at high cutoff.
|
||||||
static const constexpr int DEFAULT_OVERSAMP = 3;
|
static const constexpr int DEFAULT_OVERSAMP = 3;
|
||||||
|
|
||||||
Data::AudioFrame low = 0.0;
|
DT low = 0.0;
|
||||||
Data::AudioFrame high = 0.0;
|
DT high = 0.0;
|
||||||
Data::AudioFrame band = 0.0;
|
DT band = 0.0;
|
||||||
Data::AudioFrame notch = 0.0;
|
DT notch = 0.0;
|
||||||
|
|
||||||
SVFilter() = default;
|
GenericSVFilter() = default;
|
||||||
~SVFilter() = default;
|
~GenericSVFilter() = default;
|
||||||
// nothing used here should care about taking the raw approach
|
// nothing used here should care about taking the raw approach
|
||||||
inline SVFilter(const SVFilter& o) { std::memcpy(static_cast<void*>(this), static_cast<const void*>(&o), sizeof(SVFilter)); }
|
inline GenericSVFilter<DT>(const GenericSVFilter<DT>& o) { std::memcpy(static_cast<void*>(this), static_cast<const void*>(&o), sizeof(o)); }
|
||||||
inline SVFilter& operator=(const SVFilter& o) { std::memcpy(static_cast<void*>(this), static_cast<const void*>(&o), sizeof(SVFilter)); return *this; }
|
inline GenericSVFilter<DT>& operator=(const GenericSVFilter<DT>& o) { std::memcpy(static_cast<void*>(this), static_cast<const void*>(&o), sizeof(o)); return *this; }
|
||||||
|
|
||||||
void process(Data::AudioFrame in, double cutoff, double resonance, int oversamp = DEFAULT_OVERSAMP);
|
void process(DT in, double cutoff, double resonance, int oversamp = DEFAULT_OVERSAMP);
|
||||||
inline void reset() { low = 0.0; high = 0.0; band = 0.0; notch = 0.0; }
|
inline void reset() { low = 0.0; high = 0.0; band = 0.0; notch = 0.0; }
|
||||||
inline void normalize(double m = 1.0) {
|
inline void normalize(double m) {
|
||||||
low = low.clamp(m);
|
if constexpr (std::is_arithmetic_v<DT>) {
|
||||||
high = high.clamp(m);
|
low = std::clamp(low, -m, m);
|
||||||
band = band.clamp(m);
|
high = std::clamp(high, -m, m);
|
||||||
notch = notch.clamp(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); }
|
static inline double scaledResonance(double r) { return std::pow(10, r*5); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// 12db Chamberlin State Variable Filter
|
||||||
|
typedef GenericSVFilter<Data::AudioFrame> SVFilter;
|
||||||
|
/// 12db Chamberlin State Variable Filter (mono version)
|
||||||
|
typedef GenericSVFilter<double> SVFilterM;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue