Add resonant filter plugin
This commit is contained in:
parent
48eb843cfa
commit
7c36a8bf98
|
@ -1,3 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
add_subdirectory(yaw-tab)
|
add_subdirectory(yaw-tab)
|
||||||
add_subdirectory(yaw-shepard)
|
add_subdirectory(yaw-shepard)
|
||||||
|
add_subdirectory(yaw-vowel)
|
|
@ -4,6 +4,7 @@ dpf_add_plugin(yaw-vowel
|
||||||
TARGETS vst2
|
TARGETS vst2
|
||||||
FILES_DSP
|
FILES_DSP
|
||||||
dsp.cpp
|
dsp.cpp
|
||||||
|
filter.cpp
|
||||||
FILES_UI
|
FILES_UI
|
||||||
wtutil.cpp
|
wtutil.cpp
|
||||||
wintab.cpp
|
wintab.cpp
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "DistrhoPlugin.hpp"
|
#include "DistrhoPlugin.hpp"
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
START_NAMESPACE_DISTRHO
|
START_NAMESPACE_DISTRHO
|
||||||
|
|
||||||
|
@ -7,7 +8,7 @@ class TabPlugin : public Plugin
|
||||||
public:
|
public:
|
||||||
TabPlugin()
|
TabPlugin()
|
||||||
: Plugin(kParameterCount, 0, 0),
|
: Plugin(kParameterCount, 0, 0),
|
||||||
sampleRate(getSampleRate())
|
hzNyq(0.5 * getSampleRate())
|
||||||
{
|
{
|
||||||
// clear all parameters
|
// clear all parameters
|
||||||
std::memset(fParameters, 0, sizeof(float) * kParameterCount);
|
std::memset(fParameters, 0, sizeof(float) * kParameterCount);
|
||||||
|
@ -15,13 +16,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const char* getLabel() const override { return "yaw-tab"; }
|
const char* getLabel() const override { return "yaw-vowel"; }
|
||||||
const char* getDescription() const override { return "Drawing tablet synth UI"; }
|
const char* getDescription() const override { return "Drawing tablet synth UI"; }
|
||||||
const char* getMaker() const override { return "yaw-audio"; }
|
const char* getMaker() const override { return "yaw-audio"; }
|
||||||
const char* getHomePage() const override { return "https://yaw.man/plugins/yaw-tab"; }
|
const char* getHomePage() const override { return "https://yaw.man/plugins/yaw-vowel"; }
|
||||||
const char* getLicense() const override { return "ISC"; }
|
const char* getLicense() const override { return "Fuck you pay me"; }
|
||||||
uint32_t getVersion() const override { return d_version(1, 0, 0); }
|
uint32_t getVersion() const override { return d_version(1, 0, 0); }
|
||||||
int64_t getUniqueId() const override { return d_cconst('y', 'w', 't', 'b'); }
|
int64_t getUniqueId() const override { return d_cconst('y', 'v', 'w', 'l'); }
|
||||||
|
|
||||||
|
|
||||||
void initParameter(uint32_t index, Parameter& parameter) override
|
void initParameter(uint32_t index, Parameter& parameter) override
|
||||||
|
@ -69,7 +70,7 @@ protected:
|
||||||
|
|
||||||
void sampleRateChanged(double newRate) override
|
void sampleRateChanged(double newRate) override
|
||||||
{
|
{
|
||||||
sampleRate = newRate;
|
hzNyq = newRate / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getParameterValue(uint32_t index) const override
|
float getParameterValue(uint32_t index) const override
|
||||||
|
@ -80,49 +81,25 @@ protected:
|
||||||
void setParameterValue(uint32_t idx, float val) override
|
void setParameterValue(uint32_t idx, float val) override
|
||||||
{
|
{
|
||||||
fParameters[idx] = val;
|
fParameters[idx] = val;
|
||||||
switch (idx) {
|
if( kParameterTime == idx ) return;
|
||||||
case ktpax:
|
double x = (fParameters[ktpax] * 700.0 + 200.0) / (2.0 * hzNyq);
|
||||||
period = 0.02f * val * static_cast<float>(sampleRate);
|
double y = (fParameters[ktpay] * 1900.0 + 500.0) / (2.0 * hzNyq);
|
||||||
break;
|
double p = fParameters[ktpap];
|
||||||
case ktpay:
|
filter.set(x, y, p);
|
||||||
break;
|
|
||||||
case ktpaz:
|
|
||||||
break;
|
|
||||||
case ktpap:
|
|
||||||
volume = val;
|
|
||||||
break;
|
|
||||||
case kParameterButtonA:
|
|
||||||
break;
|
|
||||||
case kParameterButtonB:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(const float** inputs, float** outputs, uint32_t frames) override
|
void run(const float** inputs, float** outputs, uint32_t frames) override
|
||||||
{
|
{
|
||||||
|
filter.process(outputs, inputs, frames);
|
||||||
for (uint32_t i = 0; i < frames; ++i) {
|
|
||||||
counter++;
|
|
||||||
if (counter > period) {
|
|
||||||
outputs[0][i] = outputs[1][i] = volume;
|
|
||||||
counter = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
outputs[0][i] = outputs[1][i] = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parity = !parity;
|
parity = !parity;
|
||||||
fParameters[kParameterTime] += parity ? 1 : -1;
|
fParameters[kParameterTime] += parity ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float fParameters[kParameterCount];
|
float fParameters[kParameterCount];
|
||||||
float period = 0.f;
|
double hzNyq;
|
||||||
float counter = 0.f;
|
|
||||||
float volume = 0.f;
|
|
||||||
double sampleRate;
|
|
||||||
bool parity = false;
|
bool parity = false;
|
||||||
|
Filter filter;
|
||||||
|
|
||||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TabPlugin)
|
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TabPlugin)
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
|
void Resonator::clear()
|
||||||
|
{
|
||||||
|
xp = xpp = yp = ypp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resonator::process(float* output, const float* const input, uint32_t frames)
|
||||||
|
{
|
||||||
|
for(uint32_t i = 0; i < frames; ++i){
|
||||||
|
float x = static_cast<float>(input[i] * scale);
|
||||||
|
float y = x - xpp - app * ypp + ap * yp;
|
||||||
|
output[i] = y;
|
||||||
|
xpp = xp;
|
||||||
|
xp = x;
|
||||||
|
ypp = yp;
|
||||||
|
yp = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resonator::set(double _app, double _ap, double _scale)
|
||||||
|
{
|
||||||
|
app = _app; ap = _ap; scale = _scale;
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include "DistrhoPlugin.hpp"
|
||||||
|
#include <tuple>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
class Resonator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Resonator():
|
||||||
|
xp(0), xpp(0), yp(0), ypp(0), app(0), ap(0), scale(1){};
|
||||||
|
|
||||||
|
void process(float *output, const float *const input, uint32_t frames);
|
||||||
|
void clear();
|
||||||
|
void set(double _app, double _ap, double _scale);
|
||||||
|
|
||||||
|
private:
|
||||||
|
float xp;
|
||||||
|
float xpp;
|
||||||
|
float yp;
|
||||||
|
float ypp;
|
||||||
|
double app;
|
||||||
|
double ap;
|
||||||
|
double scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Filter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Filter(){};
|
||||||
|
|
||||||
|
void process(float **outputs, const float **inputs, uint32_t frames)
|
||||||
|
{
|
||||||
|
for (uint chn = 0; chn < 2; ++chn)
|
||||||
|
{
|
||||||
|
for (uint32_t j = 0; j < frames; ++j)
|
||||||
|
{
|
||||||
|
outputs[chn][j] = inputs[chn][j];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& r : res[chn])
|
||||||
|
{
|
||||||
|
r.process(outputs[chn], outputs[chn], frames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Compute filter coefficients from
|
||||||
|
//frequency as a proportion of the sample rate
|
||||||
|
//REMEMBER: THAT'S DOUBLE THE Nyquist RATE, dummy
|
||||||
|
//and resonance in [0, 1]
|
||||||
|
void set(double x, double y, double p)
|
||||||
|
{
|
||||||
|
double r = p * 0.99;
|
||||||
|
double app = r * r;
|
||||||
|
double xap = (1.0 + r * r) * cos(M_PI * x);
|
||||||
|
double yap = (1.0 + r * r) * cos(M_PI * y);
|
||||||
|
double scale = sqrt(0.5 - 0.5 * r * r);
|
||||||
|
for (auto& channelFilter : res)
|
||||||
|
{
|
||||||
|
channelFilter[0].set(app, xap, scale);
|
||||||
|
channelFilter[1].set(app, xap, scale);
|
||||||
|
channelFilter[2].set(app, yap, scale);
|
||||||
|
channelFilter[3].set(app, yap, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<std::array<Resonator, 4>, 2> res;
|
||||||
|
};
|
Loading…
Reference in New Issue