Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
| 467142603d |
14 changed files with 137 additions and 602 deletions
2
Makefile
2
Makefile
|
|
@ -3,7 +3,7 @@
|
||||||
# ------------------------------ #
|
# ------------------------------ #
|
||||||
|
|
||||||
# Define your plugins here as space-separated names
|
# Define your plugins here as space-separated names
|
||||||
PLUGINS = SquidgeDistortion SquidgeFilter
|
PLUGINS = SquidgeDistortion
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
# --------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
160
core/Filter.cpp
160
core/Filter.cpp
|
|
@ -1,129 +1,71 @@
|
||||||
#include "Filter.hpp"
|
#include "Filter.hpp"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#ifndef M_PI
|
Filter::Filter(float initCutOff, float initSampleRate)
|
||||||
#define M_PI 3.14159265358979323846
|
: cutOff_(initCutOff), feedback_(0.0f), resonance_(0.1f), a1_(0.0f),
|
||||||
#endif
|
a2_(0.0f), a3_(0.0f), g_(0.0f), k_(2.0f), sampleRate_(initSampleRate),
|
||||||
|
s1L_(0.0f), s2L_(0.0f), s1R_(0.0f), s2R_(0.0f), outZL_(0.0f),
|
||||||
|
outZR_(0.0f) {
|
||||||
|
recompute();
|
||||||
|
};
|
||||||
|
|
||||||
Filter::Filter(float initCutOff, float initQ, float initSampleRate)
|
void Filter::process(const float *in, float *out, uint32_t frames) {
|
||||||
: modulation_(0.0f), cutOff_(initCutOff), q_(initQ),
|
filter(in, out, frames, &s1L_, &s2L_, &outZL_);
|
||||||
sampleRate_(initSampleRate), type_(kLowPass), g_(0.0f), lpL_(0.0f),
|
};
|
||||||
bpL_(0.0f), lpR_(0.0f), bpR_(0.0f) {
|
void Filter::processStereo(const float *inLeft, const float *inRight,
|
||||||
updateCoeffs();
|
float *outLeft, float *outRight, uint32_t frames) {
|
||||||
}
|
filter(inLeft, outLeft, frames, &s1L_, &s2L_, &outZL_);
|
||||||
|
filter(inRight, outRight, frames, &s1R_, &s2R_, &outZR_);
|
||||||
Filter::FilterType Filter::getType() const { return type_; }
|
};
|
||||||
|
|
||||||
float Filter::clampFreq(float freq) {
|
|
||||||
return std::fmin(std::fmax(freq, kFilterMin), kFilterMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Filter::updateCoeffs() {
|
|
||||||
float totalFreq = clampFreq(cutOff_ + modulation_);
|
|
||||||
|
|
||||||
float f = totalFreq / std::fmax(sampleRate_, 1.0f);
|
|
||||||
|
|
||||||
if (f > kMaxNormalizedFrequency)
|
|
||||||
f = kMaxNormalizedFrequency;
|
|
||||||
if (f < 0.0001f)
|
|
||||||
f = 0.0001f;
|
|
||||||
|
|
||||||
g_ = 2.0f * std::sin(M_PI * f);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Filter::processFrame(float input, float &lp, float &bp) const {
|
|
||||||
float hp = input - (bp / q_) - lp;
|
|
||||||
|
|
||||||
bp = bp + g_ * hp;
|
|
||||||
lp = lp + g_ * bp;
|
|
||||||
|
|
||||||
switch (type_) {
|
|
||||||
case kHighPass:
|
|
||||||
return hp;
|
|
||||||
case kBandPass:
|
|
||||||
return bp;
|
|
||||||
case kNotch:
|
|
||||||
return input - lp;
|
|
||||||
case kLowPass:
|
|
||||||
default:
|
|
||||||
return lp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Filter::process(const float *in, float *out, uint32_t frames,
|
|
||||||
const float *modulation) {
|
|
||||||
float lp = lpL_;
|
|
||||||
float bp = bpL_;
|
|
||||||
|
|
||||||
|
void Filter::filter(const float *in, float *out, uint32_t frames, float *s1,
|
||||||
|
float *s2, float *outZ) {
|
||||||
for (uint32_t i = 0; i < frames; ++i) {
|
for (uint32_t i = 0; i < frames; ++i) {
|
||||||
if (modulation != nullptr) {
|
float x = in[i] + (feedback_ * (*outZ));
|
||||||
if (std::abs(modulation[i] - modulation_) > 0.001f) {
|
float v3 = x - *s2;
|
||||||
setModulation(modulation[i]);
|
if (resonance_ > 0.995f && std::fabs(v3) < 1.0e-9f) {
|
||||||
|
v3 = 1.0e-6f;
|
||||||
}
|
}
|
||||||
|
float v1 = (a1_ * (*s1)) + (a2_ * v3);
|
||||||
|
float v2 = (*s2) + (a2_ * (*s1)) + (a3_ * v3);
|
||||||
|
*s1 = (2.0f * v1) - *s1;
|
||||||
|
*s2 = (2.0f * v2) - *s2;
|
||||||
|
out[i] = v2;
|
||||||
|
*outZ = v2;
|
||||||
}
|
}
|
||||||
out[i] = processFrame(in[i], lp, bp);
|
|
||||||
}
|
|
||||||
|
|
||||||
lpL_ = lp;
|
|
||||||
bpL_ = bp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Filter::processStereo(const float *inL, const float *inR, float *outL,
|
void Filter::recompute() {
|
||||||
float *outR, uint32_t frames,
|
float sr = std::fmax(sampleRate_, 1.0f);
|
||||||
const float *modulation) {
|
float fc = std::fmin(std::fmax(cutOff_, 1.0f), 0.45f * sr);
|
||||||
float lpL = lpL_, bpL = bpL_;
|
g_ = std::tan(static_cast<float>(M_PI) * (fc / sr));
|
||||||
float lpR = lpR_, bpR = bpR_;
|
k_ = 2.0f * (1.0f - std::fmin(std::fmax(resonance_, 0.0f), 1.0f));
|
||||||
|
|
||||||
for (uint32_t i = 0; i < frames; ++i) {
|
float denom = 1.0f + (g_ * (g_ + k_));
|
||||||
if (modulation != nullptr) {
|
a1_ = 1.0f / denom;
|
||||||
if (std::abs(modulation[i] - modulation_) > 0.001f) {
|
a2_ = g_ * a1_;
|
||||||
setModulation(modulation[i]);
|
a3_ = g_ * a2_;
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
float inValL = (inL != nullptr) ? inL[i] : 0.0f;
|
void Filter::setCutOff(float newCutOff) {
|
||||||
float inValR = (inR != nullptr) ? inR[i] : 0.0f;
|
cutOff_ = newCutOff;
|
||||||
|
recompute();
|
||||||
outL[i] = processFrame(inValL, lpL, bpL);
|
|
||||||
outR[i] = processFrame(inValR, lpR, bpR);
|
|
||||||
}
|
|
||||||
|
|
||||||
lpL_ = lpL;
|
|
||||||
bpL_ = bpL;
|
|
||||||
lpR_ = lpR;
|
|
||||||
bpR_ = bpR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Filter::getCutOff() const { return cutOff_; }
|
float Filter::getCutOff() const { return cutOff_; }
|
||||||
|
|
||||||
void Filter::setCutOff(float freq) {
|
void Filter::setFeedback(float newFeedback) {
|
||||||
cutOff_ = clampFreq(freq);
|
feedback_ = std::fmin(std::fmax(newFeedback, 0.0f), 0.95f);
|
||||||
updateCoeffs();
|
|
||||||
}
|
}
|
||||||
|
float Filter::getFeedback() const { return feedback_; }
|
||||||
|
|
||||||
float Filter::getQ() const { return q_; }
|
void Filter::setResonance(float newResonance) {
|
||||||
|
resonance_ = std::fmin(std::fmax(newResonance, 0.0f), 1.0f);
|
||||||
void Filter::setQ(float q) {
|
recompute();
|
||||||
q_ = std::fmin(std::fmax(q, kQMin), kQMax);
|
|
||||||
updateCoeffs();
|
|
||||||
}
|
}
|
||||||
|
float Filter::getResonance() const { return resonance_; }
|
||||||
|
|
||||||
void Filter::setType(FilterType type) { type_ = type; }
|
void Filter::setSampleRate(float newSampleRate) {
|
||||||
|
sampleRate_ = newSampleRate;
|
||||||
|
recompute();
|
||||||
|
}
|
||||||
float Filter::getSampleRate() const { return sampleRate_; }
|
float Filter::getSampleRate() const { return sampleRate_; }
|
||||||
|
|
||||||
void Filter::setSampleRate(float sr) {
|
|
||||||
if (sr > 0.0f) {
|
|
||||||
sampleRate_ = sr;
|
|
||||||
updateCoeffs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Filter::getModulation() const { return modulation_; }
|
|
||||||
|
|
||||||
void Filter::setModulation(float mod) {
|
|
||||||
if (std::abs(modulation_ - mod) > 0.0001f) {
|
|
||||||
modulation_ = mod;
|
|
||||||
updateCoeffs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +1,45 @@
|
||||||
#ifndef FILTER_HPP_INCLUDED
|
#ifndef FILTER_HPP_INCLUDED
|
||||||
#define FILTER_HPP_INCLUDED
|
#define FILTER_HPP_INCLUDED
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
constexpr float kMaxNormalizedFrequency = 0.16667f;
|
|
||||||
constexpr float kFilterMin = 20.0f;
|
|
||||||
constexpr float kFilterMax = 10000.0f;
|
|
||||||
constexpr float kQMin = 0.1f;
|
|
||||||
constexpr float kQMax = 20.0f;
|
|
||||||
|
|
||||||
class Filter {
|
class Filter {
|
||||||
public:
|
public:
|
||||||
Filter(float initCutOff = 1000.0f, float initQ = 0.707f,
|
Filter(float initCutOff = 1.0f, float initSampleRate = 48000.0f);
|
||||||
float initSampleRate = 48000.0f);
|
void process(const float *in, float *out, uint32_t frames);
|
||||||
|
void processStereo(const float *inLeft, const float *inRight, float *outLeft,
|
||||||
|
float *outRight, uint32_t frames);
|
||||||
|
|
||||||
enum FilterType { kLowPass, kHighPass, kBandPass, kNotch, kFilterTypeCount };
|
void recompute();
|
||||||
|
void setCutOff(float newCutOff);
|
||||||
void setCutOff(float freq);
|
|
||||||
float getCutOff() const;
|
float getCutOff() const;
|
||||||
|
void setFeedback(float newFeedback);
|
||||||
void setQ(float q);
|
float getFeedback() const;
|
||||||
float getQ() const;
|
void setResonance(float newResonance);
|
||||||
void setSampleRate(float sr);
|
float getResonance() const;
|
||||||
|
void setSampleRate(float newSampleRate);
|
||||||
float getSampleRate() const;
|
float getSampleRate() const;
|
||||||
void setType(FilterType type);
|
|
||||||
FilterType getType() const;
|
|
||||||
void setModulation(float mod);
|
|
||||||
float getModulation() const;
|
|
||||||
|
|
||||||
void process(const float *in, float *out, uint32_t frames,
|
|
||||||
const float *modulation = nullptr);
|
|
||||||
void processStereo(const float *inL, const float *inR, float *outL,
|
|
||||||
float *outR, uint32_t frames,
|
|
||||||
const float *modulation = nullptr);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateCoeffs();
|
void filter(const float *in, float *out, uint32_t frames, float *s1,
|
||||||
float modulation_;
|
float *s2, float *outZ);
|
||||||
|
|
||||||
float clampFreq(float freq);
|
|
||||||
float processFrame(float input, float &lp, float &bp) const;
|
|
||||||
|
|
||||||
float cutOff_;
|
float cutOff_;
|
||||||
float q_;
|
float feedback_;
|
||||||
float sampleRate_;
|
float resonance_;
|
||||||
FilterType type_;
|
float a1_;
|
||||||
|
float a2_;
|
||||||
|
float a3_;
|
||||||
float g_;
|
float g_;
|
||||||
|
float k_;
|
||||||
float lpL_, bpL_;
|
float sampleRate_;
|
||||||
float lpR_, bpR_;
|
float s1L_;
|
||||||
|
float s2L_;
|
||||||
|
float s1R_;
|
||||||
|
float s2R_;
|
||||||
|
float outZL_;
|
||||||
|
float outZR_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // FILTER_HPP_INCLUDED
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
#include "Oscillator.hpp"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
Oscillator::Oscillator(float initFreq)
|
|
||||||
: freq_(initFreq), gain_(100.0f), waveShape_(kWaveShapeSine),
|
|
||||||
sampleRate_(48000.f), phase_(0.0f), inc_(0.0f)
|
|
||||||
{
|
|
||||||
recalc_();
|
|
||||||
};
|
|
||||||
|
|
||||||
void Oscillator::process(float *out, uint32_t frames)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < frames; ++i)
|
|
||||||
{
|
|
||||||
switch (waveShape_)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case kWaveShapeSine:
|
|
||||||
out[i] = std::sinf(phase_ * 2.0f * M_PI) * gain_;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
phase_ += inc_;
|
|
||||||
if (phase_ >= 1.0f)
|
|
||||||
phase_ -= 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Oscillator::reset() { phase_ = 0; }
|
|
||||||
|
|
||||||
void Oscillator::recalc_() { inc_ = freq_ / sampleRate_; }
|
|
||||||
|
|
||||||
void Oscillator::setFrequency(float newFreq)
|
|
||||||
{
|
|
||||||
freq_ = std::fmax(newFreq, 0.0f);
|
|
||||||
recalc_();
|
|
||||||
}
|
|
||||||
float Oscillator::getFrequency() const { return freq_; };
|
|
||||||
|
|
||||||
void Oscillator::setGain(float newGain)
|
|
||||||
{
|
|
||||||
gain_ = newGain > 0 ? newGain : 1.0f;
|
|
||||||
}
|
|
||||||
float Oscillator::getGain() const { return gain_; };
|
|
||||||
|
|
||||||
void Oscillator::setSampleRate(float newSampleRate)
|
|
||||||
{
|
|
||||||
sampleRate_ = newSampleRate > 0 ? newSampleRate : 48000.0f;
|
|
||||||
recalc_();
|
|
||||||
}
|
|
||||||
float Oscillator::getSampleRate() const { return sampleRate_; }
|
|
||||||
|
|
||||||
void Oscillator::setWaveShape(WaveShape shape) { waveShape_ = shape; }
|
|
||||||
Oscillator::WaveShape Oscillator::getWaveShape() const { return waveShape_; }
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#ifndef OSCILLATOR_HPP_INCLUDED
|
|
||||||
#define OSCILLATOR_HPP_INCLUDED
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#ifndef M_PI
|
|
||||||
#define M_PI 3.14159265358979323846
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class Oscillator {
|
|
||||||
enum WaveShape { kWaveShapeSine, kWaveShapeTriangle, kWaveShapeSquare };
|
|
||||||
|
|
||||||
public:
|
|
||||||
Oscillator(float initFreq);
|
|
||||||
void process(float *out, uint32_t frames);
|
|
||||||
|
|
||||||
void setFrequency(float newFreq);
|
|
||||||
float getFrequency() const;
|
|
||||||
|
|
||||||
void setGain(float newGain);
|
|
||||||
float getGain() const;
|
|
||||||
|
|
||||||
void setSampleRate(float newSampleRate);
|
|
||||||
float getSampleRate() const;
|
|
||||||
|
|
||||||
void setWaveShape(WaveShape shape);
|
|
||||||
WaveShape getWaveShape() const;
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
|
||||||
float freq_;
|
|
||||||
float gain_;
|
|
||||||
WaveShape waveShape_;
|
|
||||||
float sampleRate_;
|
|
||||||
float phase_;
|
|
||||||
float inc_;
|
|
||||||
void recalc_();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // OSCILLATOR_HPP_INCLUDED
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
#define DISTRHO_PLUGIN_NUM_INPUTS 2
|
#define DISTRHO_PLUGIN_NUM_INPUTS 2
|
||||||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2
|
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_NUM_PARAMETERS 5
|
#define DISTRHO_PLUGIN_NUM_PARAMETERS 6
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 0
|
#define DISTRHO_PLUGIN_WANT_PROGRAMS 0
|
||||||
#define DISTRHO_PLUGIN_WANT_STATE 0
|
#define DISTRHO_PLUGIN_WANT_STATE 0
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/make -f
|
#!/usr/bin/make -f
|
||||||
NAME = SquidgeDistortion
|
NAME = SquidgeDistortion
|
||||||
|
|
||||||
FILES_DSP = SquidgeDistortion.cpp ../../core/Gain.cpp ../../core/Clipper.cpp ../../core/Mixer.cpp
|
FILES_DSP = SquidgeDistortion.cpp ../../core/Gain.cpp ../../core/Clipper.cpp ../../core/Mixer.cpp ../../core/Filter.cpp
|
||||||
|
|
||||||
TARGETS = vst3 clap
|
TARGETS = vst3 clap
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "../../core/Clipper.hpp"
|
#include "../../core/Clipper.hpp"
|
||||||
|
#include "../../core/Filter.hpp"
|
||||||
#include "../../core/Gain.hpp"
|
#include "../../core/Gain.hpp"
|
||||||
#include "../../core/Mixer.hpp"
|
#include "../../core/Mixer.hpp"
|
||||||
|
|
||||||
|
|
@ -26,11 +27,14 @@ public:
|
||||||
enum Parameters {
|
enum Parameters {
|
||||||
kParamGain,
|
kParamGain,
|
||||||
kParamClipMode,
|
kParamClipMode,
|
||||||
|
kParamFilter,
|
||||||
|
kParamFilterFeedback,
|
||||||
kParamMixVolume,
|
kParamMixVolume,
|
||||||
|
kParamResonance,
|
||||||
kParameterCount // must be last
|
kParameterCount // must be last
|
||||||
};
|
};
|
||||||
SquidgeDistortion()
|
SquidgeDistortion()
|
||||||
: Plugin(kParameterCount, 0, 0), gain_(2.0f), mixer_(1.0f) {
|
: Plugin(kParameterCount, 0, 0), gain_(2.0f), mixer_(1.0f), filter_(440) {
|
||||||
mixer_.setInputGain(kChannelDry, 0.0f);
|
mixer_.setInputGain(kChannelDry, 0.0f);
|
||||||
mixer_.setInputGain(kChannelWet, 1.0f);
|
mixer_.setInputGain(kChannelWet, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
@ -71,6 +75,22 @@ protected:
|
||||||
parameter.enumValues.values =
|
parameter.enumValues.values =
|
||||||
const_cast<ParameterEnumerationValue *>(sClipModes);
|
const_cast<ParameterEnumerationValue *>(sClipModes);
|
||||||
break;
|
break;
|
||||||
|
case kParamFilter:
|
||||||
|
parameter.name = "Filter";
|
||||||
|
parameter.symbol = "filter";
|
||||||
|
parameter.ranges.min = 20.0f;
|
||||||
|
parameter.ranges.def = 1000.0f;
|
||||||
|
parameter.ranges.max = 10000.0f;
|
||||||
|
parameter.hints = kParameterIsAutomatable;
|
||||||
|
break;
|
||||||
|
case kParamFilterFeedback:
|
||||||
|
parameter.name = "Feedback";
|
||||||
|
parameter.symbol = "filterfeedback";
|
||||||
|
parameter.ranges.min = 0.0f;
|
||||||
|
parameter.ranges.def = 0.0f;
|
||||||
|
parameter.ranges.max = 0.95f;
|
||||||
|
parameter.hints = kParameterIsAutomatable;
|
||||||
|
break;
|
||||||
case kParamMixVolume:
|
case kParamMixVolume:
|
||||||
parameter.name = "Dry/Wet";
|
parameter.name = "Dry/Wet";
|
||||||
parameter.symbol = "drywetvolume";
|
parameter.symbol = "drywetvolume";
|
||||||
|
|
@ -79,6 +99,14 @@ protected:
|
||||||
parameter.ranges.max = 1.0f;
|
parameter.ranges.max = 1.0f;
|
||||||
parameter.hints = kParameterIsAutomatable;
|
parameter.hints = kParameterIsAutomatable;
|
||||||
break;
|
break;
|
||||||
|
case kParamResonance:
|
||||||
|
parameter.name = "Resonance";
|
||||||
|
parameter.symbol = "resonance";
|
||||||
|
parameter.ranges.min = 0.0f;
|
||||||
|
parameter.ranges.def = 0.1f;
|
||||||
|
parameter.ranges.max = 1.0f;
|
||||||
|
parameter.hints = kParameterIsAutomatable;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,8 +116,14 @@ protected:
|
||||||
return gain_.getGain();
|
return gain_.getGain();
|
||||||
case kParamClipMode:
|
case kParamClipMode:
|
||||||
return (float)clipper_.getMode();
|
return (float)clipper_.getMode();
|
||||||
|
case kParamFilter:
|
||||||
|
return (float)filter_.getCutOff();
|
||||||
|
case kParamFilterFeedback:
|
||||||
|
return (float)filter_.getFeedback();
|
||||||
case kParamMixVolume:
|
case kParamMixVolume:
|
||||||
return mixer_.getInputGain(kChannelWet);
|
return mixer_.getInputGain(kChannelWet);
|
||||||
|
case kParamResonance:
|
||||||
|
return (float)filter_.getResonance();
|
||||||
}
|
}
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
@ -104,10 +138,19 @@ protected:
|
||||||
static_cast<float>(Clipper::kClipperModeCount - 1));
|
static_cast<float>(Clipper::kClipperModeCount - 1));
|
||||||
clipper_.setMode(static_cast<Clipper::ClipperMode>(std::lround(value)));
|
clipper_.setMode(static_cast<Clipper::ClipperMode>(std::lround(value)));
|
||||||
break;
|
break;
|
||||||
|
case kParamFilter:
|
||||||
|
filter_.setCutOff(value);
|
||||||
|
break;
|
||||||
|
case kParamFilterFeedback:
|
||||||
|
filter_.setFeedback(value);
|
||||||
|
break;
|
||||||
case kParamMixVolume:
|
case kParamMixVolume:
|
||||||
mixer_.setInputGain(kChannelWet, value);
|
mixer_.setInputGain(kChannelWet, value);
|
||||||
mixer_.setInputGain(kChannelDry, 1.0f - value);
|
mixer_.setInputGain(kChannelDry, 1.0f - value);
|
||||||
break;
|
break;
|
||||||
|
case kParamResonance:
|
||||||
|
filter_.setResonance(value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,17 +166,24 @@ protected:
|
||||||
buffers_.clippedR, frames);
|
buffers_.clippedR, frames);
|
||||||
clipper_.processStereo(buffers_.clippedL, buffers_.clippedR,
|
clipper_.processStereo(buffers_.clippedL, buffers_.clippedR,
|
||||||
buffers_.clippedL, buffers_.clippedR, frames);
|
buffers_.clippedL, buffers_.clippedR, frames);
|
||||||
|
filter_.processStereo(buffers_.clippedL, buffers_.clippedR, buffers_.lpL,
|
||||||
|
buffers_.lpR, frames);
|
||||||
|
|
||||||
const float *inputsL[2] = {inputs[0], buffers_.clippedL};
|
const float *inputsL[2] = {inputs[0], buffers_.lpL};
|
||||||
const float *inputsR[2] = {inputs[1], buffers_.clippedR};
|
const float *inputsR[2] = {inputs[1], buffers_.lpR};
|
||||||
|
|
||||||
mixer_.processStereo(inputsL, inputsR, outputs[0], outputs[1], frames);
|
mixer_.processStereo(inputsL, inputsR, outputs[0], outputs[1], frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sampleRateChanged(double newSr) override {
|
||||||
|
filter_.setSampleRate(static_cast<float>(newSr));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Gain gain_;
|
Gain gain_;
|
||||||
Clipper clipper_;
|
Clipper clipper_;
|
||||||
Mixer<2> mixer_;
|
Mixer<2> mixer_;
|
||||||
|
Filter filter_;
|
||||||
AudioBuffers buffers_;
|
AudioBuffers buffers_;
|
||||||
|
|
||||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SquidgeDistortion);
|
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SquidgeDistortion);
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED
|
|
||||||
#define DISTRHO_PLUGIN_INFO_H_INCLUDED
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_NAME "SquidgeFilter"
|
|
||||||
#define DISTRHO_PLUGIN_AUTHOR "SquidgeSoft"
|
|
||||||
#define DISTRHO_PLUGIN_URI "moe.liam.squidgesoft.SquidgeFilter"
|
|
||||||
#define DISTRHO_PLUGIN_CATEGORY "fx"
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_NUM_INPUTS 2
|
|
||||||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_NUM_PARAMETERS 3
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 0
|
|
||||||
#define DISTRHO_PLUGIN_WANT_STATE 0
|
|
||||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_HAS_UI 0
|
|
||||||
#define DISTRHO_PLUGIN_IS_SYNTH 0
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_PRIV_ID "moe.liam.squidgesoft.SquidgeFilter"
|
|
||||||
#define DISTRHO_PLUGIN_BRAND "SquidgeSoft"
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_CLAP_ID "moe.liam.squidgesoft.SquidgeFilter"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
#!/usr/bin/make -f
|
|
||||||
NAME = SquidgeFilter
|
|
||||||
|
|
||||||
FILES_DSP = SquidgeFilter.cpp ../../core/Filter.cpp ../../core/Oscillator.cpp
|
|
||||||
|
|
||||||
TARGETS = vst3 clap
|
|
||||||
|
|
||||||
include ../../dpf/Makefile.plugins.mk
|
|
||||||
|
|
||||||
all: $(TARGETS)
|
|
||||||
|
|
||||||
|
|
@ -1,198 +0,0 @@
|
||||||
#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<ParameterEnumerationValue *>(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<ParameterEnumerationValue *>(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<float>(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<int>(std::fmin(std::fmax(value, 0.0f), 3.0f));
|
|
||||||
filter_.setType(static_cast<Filter::FilterType>(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<float>(timePos.bbt.beatsPerBar);
|
|
||||||
float bpm = static_cast<float>(timePos.bbt.beatsPerMinute);
|
|
||||||
float bar = static_cast<float>(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<int>(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<float>(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
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED
|
|
||||||
#define DISTRHO_PLUGIN_INFO_H_INCLUDED
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_NAME "SquidgeTemplate"
|
|
||||||
#define DISTRHO_PLUGIN_AUTHOR "SquidgeSoft"
|
|
||||||
#define DISTRHO_PLUGIN_URI "moe.liam.squidgesoft.SquidgeTemplate"
|
|
||||||
#define DISTRHO_PLUGIN_CATEGORY "fx"
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_NUM_INPUTS 2
|
|
||||||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_NUM_PARAMETERS 1
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 0
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 0
|
|
||||||
#define DISTRHO_PLUGIN_WANT_STATE 0
|
|
||||||
#define DISTRHO_PLUGIN_HAS_UI 0
|
|
||||||
#define DISTRHO_PLUGIN_IS_SYNTH 0
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_PRIV_ID "moe.liam.squidgesoft.SquidgeTemplate"
|
|
||||||
#define DISTRHO_PLUGIN_BRAND "SquidgeSoft"
|
|
||||||
|
|
||||||
#define DISTRHO_PLUGIN_CLAP_ID "moe.liam.squidgesoft.SquidgeTemplate"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
#!/usr/bin/make -f
|
|
||||||
NAME = squidgeTemplate
|
|
||||||
|
|
||||||
FILES_DSP = squidgeTemplate.cpp ../../core/Gain.cpp
|
|
||||||
|
|
||||||
TARGETS = vst3 clap
|
|
||||||
|
|
||||||
include ../../dpf/Makefile.plugins.mk
|
|
||||||
|
|
||||||
all: $(TARGETS)
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
#include "DistrhoDetails.hpp"
|
|
||||||
#include "DistrhoPlugin.hpp"
|
|
||||||
#include "DistrhoPluginInfo.h"
|
|
||||||
|
|
||||||
#include "../../core/Gain.hpp"
|
|
||||||
|
|
||||||
START_NAMESPACE_DISTRHO
|
|
||||||
|
|
||||||
class squidgeTemplate : public Plugin
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Parameters
|
|
||||||
{
|
|
||||||
kParamGain,
|
|
||||||
kParameterCount
|
|
||||||
};
|
|
||||||
|
|
||||||
squidgeTemplate()
|
|
||||||
: Plugin(kParameterCount, 0, 0), gain_(1.0f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const char *getLabel() const override { return "squidgeTemplate"; }
|
|
||||||
const char *getDescription() const override { return "Generic squidge plugin template."; }
|
|
||||||
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', 'T', 'P'); }
|
|
||||||
|
|
||||||
void initParameter(uint32_t index, Parameter ¶meter) override
|
|
||||||
{
|
|
||||||
switch (index)
|
|
||||||
{
|
|
||||||
case kParamGain:
|
|
||||||
parameter.name = "Gain";
|
|
||||||
parameter.symbol = "gain";
|
|
||||||
parameter.ranges.min = 0.0f;
|
|
||||||
parameter.ranges.def = 1.0f;
|
|
||||||
parameter.ranges.max = 2.0f;
|
|
||||||
parameter.hints = kParameterIsAutomatable;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float getParameterValue(uint32_t index) const override
|
|
||||||
{
|
|
||||||
if (index == kParamGain)
|
|
||||||
return gain_.getGain();
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParameterValue(uint32_t index, float value) override
|
|
||||||
{
|
|
||||||
if (index == kParamGain)
|
|
||||||
gain_.setGain(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void run(const float **inputs, float **outputs, uint32_t frames) override
|
|
||||||
{
|
|
||||||
gain_.processStereo(inputs[0], inputs[1], outputs[0], outputs[1], frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sampleRateChanged(double /*newSr*/) override
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Gain gain_;
|
|
||||||
|
|
||||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(squidgeTemplate)
|
|
||||||
};
|
|
||||||
|
|
||||||
Plugin *createPlugin()
|
|
||||||
{
|
|
||||||
return new squidgeTemplate();
|
|
||||||
}
|
|
||||||
|
|
||||||
END_NAMESPACE_DISTRHO
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue