#include "DistrhoDetails.hpp" #include "DistrhoPlugin.hpp" #include "DistrhoPluginInfo.h" #include "../../core/Filter.hpp" #include "../../core/Oscillator.hpp" START_NAMESPACE_DISTRHO const int BUFFER_SIZE = 16384; class SquidgeFilter : public Plugin { public: enum Parameters { kParamFreq, kParamResonance, kParamType, kParamLFOSyncMode, kParamLFOAmount, kParameterCount // must be last }; SquidgeFilter() : Plugin(kParameterCount, 0, 0), filter_(440.0f, 2.0f, 48000.0f), lfo_(20.0f), lfoSync_(0.0f) { filter_.setType(Filter::kLowPass); } protected: const char *getLabel() const override { return "SquidgeFilter"; } const char *getDescription() const override { return "Simple State Variable Filter."; } const char *getMaker() const override { return "SquidgeSoft"; } const char *getLicense() const override { return "GPL3"; } uint32_t getVersion() const override { return d_version(0, 1, 0); } int64_t getUniqueId() const override { return d_cconst('S', 'Q', 'F', 'T'); } void initParameter(uint32_t index, Parameter ¶meter) override { switch (index) { case kParamFreq: parameter.name = "Frequency"; parameter.symbol = "frequency"; parameter.ranges.min = 20.0f; parameter.ranges.def = 440.0f; parameter.ranges.max = 10000.0f; parameter.hints = kParameterIsAutomatable | kParameterIsLogarithmic; break; case kParamResonance: parameter.name = "Resonance"; parameter.symbol = "resonance"; parameter.ranges.min = 0.9f; parameter.ranges.def = 2.0f; parameter.ranges.max = 20.0f; parameter.hints = kParameterIsAutomatable; break; case kParamType: parameter.name = "Filter Type"; parameter.symbol = "type"; parameter.ranges.min = 0.0f; parameter.ranges.def = 0.0f; parameter.ranges.max = Filter::kFilterTypeCount - 1; parameter.hints = kParameterIsAutomatable | kParameterIsInteger; parameter.enumValues.count = Filter::kFilterTypeCount; parameter.enumValues.restrictedMode = true; static const ParameterEnumerationValue sTypes[Filter::kFilterTypeCount] = {{0.0f, "Low Pass"}, {1.0f, "High Pass"}, {2.0f, "Band Pass"}, {3.0f, "Notch"}}; parameter.enumValues.values = const_cast(sTypes); break; case kParamLFOAmount: parameter.name = "LFO Amount"; parameter.symbol = "lfoamount"; parameter.ranges.min = 0.0f; parameter.ranges.def = 0.0f; parameter.ranges.max = 1000.0f; parameter.hints = kParameterIsAutomatable | kParameterIsInteger; break; case kParamLFOSyncMode: parameter.name = "LFO Sync"; parameter.symbol = "lfosync"; parameter.ranges.min = 0.0f; parameter.ranges.def = 3.0f; parameter.ranges.max = 6.0f; parameter.hints = kParameterIsAutomatable | kParameterIsInteger; static const ParameterEnumerationValue sModes[] = { {0.0f, "1/1 Bar"}, {1.0f, "1/2 Bar"}, {2.0f, "1/4 Bar"}, {3.0f, "1/8 Bar"}, {4.0f, "1/16 Bar"}, {5.0f, "1/32 Bar"}, {6.0f, "1/64 Bar"}}; parameter.enumValues.count = 7; parameter.enumValues.restrictedMode = true; parameter.enumValues.values = const_cast(sModes); break; } } float getParameterValue(uint32_t index) const override { switch (index) { case kParamFreq: return filter_.getCutOff(); case kParamResonance: return filter_.getQ(); case kParamType: return static_cast(filter_.getType()); case kParamLFOAmount: return lfo_.getGain(); break; case kParamLFOSyncMode: return lfoSync_; }; return 0.0f; } void setParameterValue(uint32_t index, float value) override { switch (index) { case kParamFreq: filter_.setCutOff(value); break; case kParamResonance: filter_.setQ(value); break; case kParamLFOAmount: lfo_.setGain(value); break; case kParamLFOSyncMode: lfoSync_ = value; break; case kParamType: int typeIdx = static_cast(std::fmin(std::fmax(value, 0.0f), 3.0f)); filter_.setType(static_cast(typeIdx)); break; } } void run(const float **inputs, float **outputs, uint32_t frames) override { const TimePosition &timePos = getTimePosition(); float targetFreq = 4.0f; if (timePos.bbt.valid && timePos.playing && timePos.bbt.beatsPerMinute > 0.0) { float bpb = static_cast(timePos.bbt.beatsPerBar); float bpm = static_cast(timePos.bbt.beatsPerMinute); float bar = static_cast(timePos.bbt.bar); if (bar != currentBar_) { lfo_.reset(); currentBar_ = bar; } float baseFreq = (bpm / 60.0f) / bpb; static const float multipliers[] = {1.0f, 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f}; targetFreq = baseFreq * multipliers[static_cast(lfoSync_)]; } else { targetFreq = 1.0f; } lfo_.setFrequency(targetFreq); lfo_.process(lfoBuffer_, frames); filter_.processStereo(inputs[0], inputs[1], outputs[0], outputs[1], frames, lfoBuffer_); } void sampleRateChanged(double newSr) override { filter_.setSampleRate(static_cast(newSr)); lfo_.setSampleRate(newSr); } private: Filter filter_; Oscillator lfo_; float lfoSync_; uint32_t currentBar_ = 0; float lfoBuffer_[BUFFER_SIZE]; DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SquidgeFilter); }; Plugin *createPlugin() { return new SquidgeFilter(); } END_NAMESPACE_DISTRHO