|
|
@@ -1,4 +1,4 @@ |
|
|
|
#include "rack.hpp" |
|
|
|
#include <rack.hpp> |
|
|
|
|
|
|
|
|
|
|
|
using namespace rack; |
|
|
@@ -18,6 +18,7 @@ extern Model *modelHexmixVCA; |
|
|
|
extern Model *modelChoppingKinky; |
|
|
|
extern Model *modelKickall; |
|
|
|
|
|
|
|
|
|
|
|
struct Knurlie : SvgScrew { |
|
|
|
Knurlie() { |
|
|
|
sw->svg = APP->window->loadSvg(asset::plugin(pluginInstance, "res/Knurlie.svg")); |
|
|
@@ -25,3 +26,109 @@ struct Knurlie : SvgScrew { |
|
|
|
box.size = sw->box.size; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct BefacoTinyKnobRed : app::SvgKnob { |
|
|
|
BefacoTinyKnobRed() { |
|
|
|
minAngle = -0.8 * M_PI; |
|
|
|
maxAngle = 0.8 * M_PI; |
|
|
|
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoTinyKnobRed.svg"))); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct BefacoTinyKnobWhite : app::SvgKnob { |
|
|
|
BefacoTinyKnobWhite() { |
|
|
|
minAngle = -0.8 * M_PI; |
|
|
|
maxAngle = 0.8 * M_PI; |
|
|
|
setSvg(APP->window->loadSvg(asset::system("res/ComponentLibrary/BefacoTinyKnob.svg"))); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct BefacoTinyKnobGrey : app::SvgKnob { |
|
|
|
BefacoTinyKnobGrey() { |
|
|
|
minAngle = -0.8 * M_PI; |
|
|
|
maxAngle = 0.8 * M_PI; |
|
|
|
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoTinyKnobGrey.svg"))); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct Davies1900hLargeGreyKnob : Davies1900hKnob { |
|
|
|
Davies1900hLargeGreyKnob() { |
|
|
|
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Davies1900hLargeGrey.svg"))); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct BefacoOutputPort : app::SvgPort { |
|
|
|
BefacoOutputPort() { |
|
|
|
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoOutputPort.svg"))); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
struct BefacoInputPort : app::SvgPort { |
|
|
|
BefacoInputPort() { |
|
|
|
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoInputPort.svg"))); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template <typename T> |
|
|
|
T sin2pi_pade_05_5_4(T x) { |
|
|
|
x -= 0.5f; |
|
|
|
return (T(-6.283185307) * x + T(33.19863968) * simd::pow(x, 3) - T(32.44191367) * simd::pow(x, 5)) |
|
|
|
/ (1 + T(1.296008659) * simd::pow(x, 2) + T(0.7028072946) * simd::pow(x, 4)); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename T> |
|
|
|
T tanh_pade(T x) { |
|
|
|
T x2 = x * x; |
|
|
|
T q = 12.f + x2; |
|
|
|
return 12.f * x * q / (36.f * x2 + q * q); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct ADEnvelope { |
|
|
|
enum Stage { |
|
|
|
STAGE_OFF, |
|
|
|
STAGE_ATTACK, |
|
|
|
STAGE_DECAY |
|
|
|
}; |
|
|
|
|
|
|
|
Stage stage = STAGE_OFF; |
|
|
|
float env = 0.f; |
|
|
|
float attackTime = 0.1, decayTime = 0.1; |
|
|
|
float attackShape = 1.0, decayShape = 1.0; |
|
|
|
|
|
|
|
ADEnvelope() { }; |
|
|
|
|
|
|
|
void process(const float& sampleTime) { |
|
|
|
|
|
|
|
if (stage == STAGE_OFF) { |
|
|
|
env = envLinear = 0.0f; |
|
|
|
} |
|
|
|
else if (stage == STAGE_ATTACK) { |
|
|
|
envLinear += sampleTime / attackTime; |
|
|
|
env = std::pow(envLinear, attackShape); |
|
|
|
} |
|
|
|
else if (stage == STAGE_DECAY) { |
|
|
|
envLinear -= sampleTime / decayTime; |
|
|
|
env = std::pow(envLinear, decayShape); |
|
|
|
} |
|
|
|
|
|
|
|
if (envLinear >= 1.0f) { |
|
|
|
stage = STAGE_DECAY; |
|
|
|
env = envLinear = 1.0f; |
|
|
|
} |
|
|
|
else if (envLinear <= 0.0f) { |
|
|
|
stage = STAGE_OFF; |
|
|
|
env = envLinear = 0.0f; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void trigger() { |
|
|
|
stage = ADEnvelope::STAGE_ATTACK; |
|
|
|
// non-linear envelopes won't retrigger at the correct starting point if |
|
|
|
// attackShape != decayShape, so we advance the linear envelope |
|
|
|
envLinear = std::pow(env, 1.0f / attackShape); |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
float envLinear = 0.f; |
|
|
|
}; |