@@ -1,6 +1,6 @@ | |||||
{ | { | ||||
"slug": "Befaco", | "slug": "Befaco", | ||||
"version": "1.0.1", | |||||
"version": "1.1.0", | |||||
"license": "BSD-3-Clause", | "license": "BSD-3-Clause", | ||||
"name": "Befaco", | "name": "Befaco", | ||||
"author": "VCV", | "author": "VCV", | ||||
@@ -2,30 +2,19 @@ | |||||
#include "simd_input.hpp" | #include "simd_input.hpp" | ||||
static simd::float_4 clip4(simd::float_4 x) { | |||||
template <typename T> | |||||
static T clip4(T x) { | |||||
// Pade approximant of x/(1 + x^12)^(1/12) | // Pade approximant of x/(1 + x^12)^(1/12) | ||||
const simd::float_4 limit = simd::float_4(1.16691853009184); | |||||
const simd::float_4 cnst_10 = simd::float_4(10.0); | |||||
const simd::float_4 cnst_1 = simd::float_4(1.0); | |||||
const simd::float_4 cnst_01 = simd::float_4(0.1); | |||||
const simd::float_4 coeff_1 = simd::float_4(1.45833); | |||||
const simd::float_4 coeff_2 = simd::float_4(0.559028); | |||||
const simd::float_4 coeff_3 = simd::float_4(0.0427035); | |||||
const simd::float_4 coeff_4 = simd::float_4(1.54167); | |||||
const simd::float_4 coeff_5 = simd::float_4(0.642361); | |||||
const simd::float_4 coeff_6 = simd::float_4(0.0579909); | |||||
x = clamp(x*cnst_01, -limit, limit); | |||||
return cnst_10 * (x + coeff_1*simd::pow(x, 13) + coeff_2*simd::pow(x, 25) + coeff_3*simd::pow(x, 37)) | |||||
/ (cnst_1 + coeff_4*simd::pow(x, 12) + coeff_5*simd::pow(x, 24) + coeff_6*simd::pow(x, 36)); | |||||
const T limit = 1.16691853009184f; | |||||
x = clamp(x * 0.1f, -limit, limit); | |||||
return 10.0f * (x + 1.45833f * simd::pow(x, 13) + 0.559028f * simd::pow(x, 25) + 0.0427035f * simd::pow(x, 37)) | |||||
/ (1.0f + 1.54167f * simd::pow(x, 12) + 0.642361f * simd::pow(x, 24) + 0.0579909f * simd::pow(x, 36)); | |||||
} | } | ||||
static float exponentialBipolar80Pade_5_4(float x) { | static float exponentialBipolar80Pade_5_4(float x) { | ||||
return (0.109568*x + 0.281588*std::pow(x, 3) + 0.133841*std::pow(x, 5)) | |||||
/ (1. - 0.630374*std::pow(x, 2) + 0.166271*std::pow(x, 4)); | |||||
return (0.109568 * x + 0.281588 * std::pow(x, 3) + 0.133841 * std::pow(x, 5)) | |||||
/ (1. - 0.630374 * std::pow(x, 2) + 0.166271 * std::pow(x, 4)); | |||||
} | } | ||||
@@ -57,7 +46,6 @@ struct ABC : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
ABC() { | ABC() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
configParam(B1_LEVEL_PARAM, -1.0, 1.0, 0.0, "B1 Level"); | configParam(B1_LEVEL_PARAM, -1.0, 1.0, 0.0, "B1 Level"); | ||||
@@ -66,7 +54,6 @@ struct ABC : Module { | |||||
configParam(C2_LEVEL_PARAM, -1.0, 1.0, 0.0, "C2 Level"); | configParam(C2_LEVEL_PARAM, -1.0, 1.0, 0.0, "C2 Level"); | ||||
} | } | ||||
void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
simd::float_4 a1[4] = {}; | simd::float_4 a1[4] = {}; | ||||
@@ -87,7 +74,7 @@ struct ABC : Module { | |||||
// process upper section | // process upper section | ||||
if(outputs[OUT1_OUTPUT].isConnected() || outputs[OUT2_OUTPUT].isConnected() ) { | |||||
if (outputs[OUT1_OUTPUT].isConnected() || outputs[OUT2_OUTPUT].isConnected()) { | |||||
int channels_A1 = inputs[A1_INPUT].getChannels(); | int channels_A1 = inputs[A1_INPUT].getChannels(); | ||||
int channels_B1 = inputs[B1_INPUT].getChannels(); | int channels_B1 = inputs[B1_INPUT].getChannels(); | ||||
@@ -97,33 +84,41 @@ struct ABC : Module { | |||||
channels_1 = std::max(channels_1, channels_B1); | channels_1 = std::max(channels_1, channels_B1); | ||||
channels_1 = std::max(channels_1, channels_C1); | channels_1 = std::max(channels_1, channels_C1); | ||||
float mult_B1 = (2.f/5.f)*exponentialBipolar80Pade_5_4(params[B1_LEVEL_PARAM].getValue()); | |||||
float mult_B1 = (2.f / 5.f) * exponentialBipolar80Pade_5_4(params[B1_LEVEL_PARAM].getValue()); | |||||
float mult_C1 = exponentialBipolar80Pade_5_4(params[C1_LEVEL_PARAM].getValue()); | float mult_C1 = exponentialBipolar80Pade_5_4(params[C1_LEVEL_PARAM].getValue()); | ||||
if(inputs[A1_INPUT].isConnected()) load_input(inputs[A1_INPUT], a1, channels_A1); | |||||
else memset(a1, 0, sizeof(a1)); | |||||
if (inputs[A1_INPUT].isConnected()) | |||||
load_input(inputs[A1_INPUT], a1, channels_A1); | |||||
else | |||||
memset(a1, 0, sizeof(a1)); | |||||
if(inputs[B1_INPUT].isConnected()) { | |||||
if (inputs[B1_INPUT].isConnected()) { | |||||
load_input(inputs[B1_INPUT], b1, channels_B1); | load_input(inputs[B1_INPUT], b1, channels_B1); | ||||
for(int c=0; c<channels_1; c+=4) b1[c/4] *= simd::float_4(mult_B1); | |||||
} else { | |||||
for(int c=0; c<channels_1; c+=4) b1[c/4] = simd::float_4(5.f*mult_B1); | |||||
for (int c = 0; c < channels_1; c += 4) | |||||
b1[c / 4] *= simd::float_4(mult_B1); | |||||
} | |||||
else { | |||||
for (int c = 0; c < channels_1; c += 4) | |||||
b1[c / 4] = simd::float_4(5.f * mult_B1); | |||||
} | } | ||||
if(inputs[C1_INPUT].isConnected()) { | |||||
if (inputs[C1_INPUT].isConnected()) { | |||||
load_input(inputs[C1_INPUT], c1, channels_C1); | load_input(inputs[C1_INPUT], c1, channels_C1); | ||||
for(int c=0; c<channels_1; c+=4) c1[c/4] *= simd::float_4(mult_C1); | |||||
} else { | |||||
for(int c=0; c<channels_1; c+=4) c1[c/4] = simd::float_4(10.f*mult_C1); | |||||
for (int c = 0; c < channels_1; c += 4) | |||||
c1[c / 4] *= simd::float_4(mult_C1); | |||||
} | |||||
else { | |||||
for (int c = 0; c < channels_1; c += 4) | |||||
c1[c / 4] = simd::float_4(10.f * mult_C1); | |||||
} | } | ||||
for(int c=0; c<channels_1; c+=4) out1[c/4] = clip4(a1[c/4] * b1[c/4] + c1[c/4]); | |||||
for (int c = 0; c < channels_1; c += 4) | |||||
out1[c / 4] = clip4(a1[c / 4] * b1[c / 4] + c1[c / 4]); | |||||
} | } | ||||
// process lower section | // process lower section | ||||
if(outputs[OUT2_OUTPUT].isConnected()) { | |||||
if (outputs[OUT2_OUTPUT].isConnected()) { | |||||
int channels_A2 = inputs[A2_INPUT].getChannels(); | int channels_A2 = inputs[A2_INPUT].getChannels(); | ||||
int channels_B2 = inputs[B2_INPUT].getChannels(); | int channels_B2 = inputs[B2_INPUT].getChannels(); | ||||
int channels_C2 = inputs[C2_INPUT].getChannels(); | int channels_C2 = inputs[C2_INPUT].getChannels(); | ||||
@@ -132,43 +127,54 @@ struct ABC : Module { | |||||
channels_2 = std::max(channels_2, channels_B2); | channels_2 = std::max(channels_2, channels_B2); | ||||
channels_2 = std::max(channels_2, channels_C2); | channels_2 = std::max(channels_2, channels_C2); | ||||
float mult_B2 = (2.f/5.f)*exponentialBipolar80Pade_5_4(params[B2_LEVEL_PARAM].getValue()); | |||||
float mult_B2 = (2.f / 5.f) * exponentialBipolar80Pade_5_4(params[B2_LEVEL_PARAM].getValue()); | |||||
float mult_C2 = exponentialBipolar80Pade_5_4(params[C2_LEVEL_PARAM].getValue()); | float mult_C2 = exponentialBipolar80Pade_5_4(params[C2_LEVEL_PARAM].getValue()); | ||||
if(inputs[A2_INPUT].isConnected()) load_input(inputs[A2_INPUT], a2, channels_A2); | |||||
else memset(a2, 0, sizeof(a2)); | |||||
if (inputs[A2_INPUT].isConnected()) | |||||
load_input(inputs[A2_INPUT], a2, channels_A2); | |||||
else | |||||
memset(a2, 0, sizeof(a2)); | |||||
if(inputs[B2_INPUT].isConnected()) { | |||||
if (inputs[B2_INPUT].isConnected()) { | |||||
load_input(inputs[B2_INPUT], b2, channels_B2); | load_input(inputs[B2_INPUT], b2, channels_B2); | ||||
for(int c=0; c<channels_2; c+=4) b2[c/4] *= simd::float_4(mult_B2); | |||||
} else { | |||||
for(int c=0; c<channels_2; c+=4) b2[c/4] = simd::float_4(5.f*mult_B2); | |||||
for (int c = 0; c < channels_2; c += 4) | |||||
b2[c / 4] *= simd::float_4(mult_B2); | |||||
} | |||||
else { | |||||
for (int c = 0; c < channels_2; c += 4) | |||||
b2[c / 4] = simd::float_4(5.f * mult_B2); | |||||
} | } | ||||
if(inputs[C2_INPUT].isConnected()) { | |||||
if (inputs[C2_INPUT].isConnected()) { | |||||
load_input(inputs[C2_INPUT], c2, channels_C2); | load_input(inputs[C2_INPUT], c2, channels_C2); | ||||
for(int c=0; c<channels_2; c+=4) c2[c/4] *= simd::float_4(mult_C2); | |||||
} else { | |||||
for(int c=0; c<channels_2; c+=4) c2[c/4] = simd::float_4(10.f*mult_C2); | |||||
for (int c = 0; c < channels_2; c += 4) | |||||
c2[c / 4] *= simd::float_4(mult_C2); | |||||
} | |||||
else { | |||||
for (int c = 0; c < channels_2; c += 4) | |||||
c2[c / 4] = simd::float_4(10.f * mult_C2); | |||||
} | } | ||||
for(int c=0; c<channels_2; c+=4) out2[c/4] = clip4(a2[c/4] * b2[c/4] + c2[c/4]); | |||||
for (int c = 0; c < channels_2; c += 4) | |||||
out2[c / 4] = clip4(a2[c / 4] * b2[c / 4] + c2[c / 4]); | |||||
}; | }; | ||||
// Set outputs | // Set outputs | ||||
if (outputs[OUT1_OUTPUT].isConnected()) { | if (outputs[OUT1_OUTPUT].isConnected()) { | ||||
outputs[OUT1_OUTPUT].setChannels(channels_1); | outputs[OUT1_OUTPUT].setChannels(channels_1); | ||||
for(int c=0; c<channels_1; c+=4) out1[c/4].store(outputs[OUT1_OUTPUT].getVoltages(c)); | |||||
for (int c = 0; c < channels_1; c += 4) | |||||
out1[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c)); | |||||
} | } | ||||
else { | else { | ||||
for(int c=0; c<channels_1; c+=4) out2[c/4] += out1[c/4]; | |||||
for (int c = 0; c < channels_1; c += 4) | |||||
out2[c / 4] += out1[c / 4]; | |||||
channels_2 = std::max(channels_1, channels_2); | channels_2 = std::max(channels_1, channels_2); | ||||
} | } | ||||
if (outputs[OUT2_OUTPUT].isConnected()) { | if (outputs[OUT2_OUTPUT].isConnected()) { | ||||
outputs[OUT2_OUTPUT].setChannels(channels_2); | outputs[OUT2_OUTPUT].setChannels(channels_2); | ||||
for(int c=0; c<channels_2; c+=4) out2[c/4].store(outputs[OUT2_OUTPUT].getVoltages(c)); | |||||
for (int c = 0; c < channels_2; c += 4) | |||||
out2[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); | |||||
} | } | ||||
// Lights | // Lights | ||||
@@ -176,31 +182,31 @@ struct ABC : Module { | |||||
float light_1; | float light_1; | ||||
float light_2; | float light_2; | ||||
if(channels_1==1) { | |||||
if (channels_1 == 1) { | |||||
light_1 = out1[0].s[0]; | light_1 = out1[0].s[0]; | ||||
lights[OUT1_LIGHT + 0].setSmoothBrightness(light_1 / 5.f, args.sampleTime); | lights[OUT1_LIGHT + 0].setSmoothBrightness(light_1 / 5.f, args.sampleTime); | ||||
lights[OUT1_LIGHT + 1].setSmoothBrightness(-light_1 / 5.f, args.sampleTime); | lights[OUT1_LIGHT + 1].setSmoothBrightness(-light_1 / 5.f, args.sampleTime); | ||||
lights[OUT1_LIGHT + 2].setBrightness(0.f); | lights[OUT1_LIGHT + 2].setBrightness(0.f); | ||||
} else { | |||||
} | |||||
else { | |||||
light_1 = 10.f; | light_1 = 10.f; | ||||
lights[OUT1_LIGHT + 0].setBrightness(0.0f); | lights[OUT1_LIGHT + 0].setBrightness(0.0f); | ||||
lights[OUT1_LIGHT + 1].setBrightness(0.0f); | lights[OUT1_LIGHT + 1].setBrightness(0.0f); | ||||
lights[OUT1_LIGHT + 2].setBrightness(light_1); | lights[OUT1_LIGHT + 2].setBrightness(light_1); | ||||
} | } | ||||
if(channels_2==1) { | |||||
if (channels_2 == 1) { | |||||
light_2 = out2[0].s[0]; | light_2 = out2[0].s[0]; | ||||
lights[OUT2_LIGHT + 0].setSmoothBrightness(light_2 / 5.f, args.sampleTime); | lights[OUT2_LIGHT + 0].setSmoothBrightness(light_2 / 5.f, args.sampleTime); | ||||
lights[OUT2_LIGHT + 1].setSmoothBrightness(-light_2 / 5.f, args.sampleTime); | lights[OUT2_LIGHT + 1].setSmoothBrightness(-light_2 / 5.f, args.sampleTime); | ||||
lights[OUT2_LIGHT + 2].setBrightness(0.f); | lights[OUT2_LIGHT + 2].setBrightness(0.f); | ||||
} else { | |||||
} | |||||
else { | |||||
light_2 = 10.f; | light_2 = 10.f; | ||||
lights[OUT2_LIGHT + 0].setBrightness(0.0f); | lights[OUT2_LIGHT + 0].setBrightness(0.0f); | ||||
lights[OUT2_LIGHT + 1].setBrightness(0.0f); | lights[OUT2_LIGHT + 1].setBrightness(0.0f); | ||||
lights[OUT2_LIGHT + 2].setBrightness(light_2); | lights[OUT2_LIGHT + 2].setBrightness(light_2); | ||||
} | |||||
} | |||||
} | } | ||||
}; | }; | ||||
@@ -35,53 +35,63 @@ struct DualAtenuverter : Module { | |||||
} | } | ||||
void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
using simd::float_4; | |||||
simd::float_4 out1[4]; | |||||
simd::float_4 out2[4]; | |||||
float_4 out1[4]; | |||||
float_4 out2[4]; | |||||
int channels1 = inputs[IN1_INPUT].getChannels(); channels1 = channels1>0?channels1:1; | |||||
int channels2 = inputs[IN2_INPUT].getChannels(); channels2 = channels2>0?channels2:1; | |||||
int channels1 = inputs[IN1_INPUT].getChannels(); | |||||
channels1 = channels1 > 0 ? channels1 : 1; | |||||
int channels2 = inputs[IN2_INPUT].getChannels(); | |||||
channels2 = channels2 > 0 ? channels2 : 1; | |||||
simd::float_4 att1 = simd::float_4(params[ATEN1_PARAM].getValue()); | |||||
simd::float_4 att2 = simd::float_4(params[ATEN2_PARAM].getValue()); | |||||
float att1 = params[ATEN1_PARAM].getValue(); | |||||
float att2 = params[ATEN2_PARAM].getValue(); | |||||
simd::float_4 offset1 = simd::float_4(params[OFFSET1_PARAM].getValue()); | |||||
simd::float_4 offset2 = simd::float_4(params[OFFSET2_PARAM].getValue()); | |||||
float offset1 = params[OFFSET1_PARAM].getValue(); | |||||
float offset2 = params[OFFSET2_PARAM].getValue(); | |||||
for (int c = 0; c < channels1; c += 4) { | |||||
out1[c / 4] = clamp(float_4::load(inputs[IN1_INPUT].getVoltages(c)) * att1 + offset1, -10.f, 10.f); | |||||
} | |||||
for (int c = 0; c < channels2; c += 4) { | |||||
out2[c / 4] = clamp(float_4::load(inputs[IN2_INPUT].getVoltages(c)) * att2 + offset2, -10.f, 10.f); | |||||
} | |||||
for (int c = 0; c < channels1; c += 4) out1[c / 4] = clamp(simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * att1 + offset1, -10.f, 10.f); | |||||
for (int c = 0; c < channels2; c += 4) out2[c / 4] = clamp(simd::float_4::load(inputs[IN2_INPUT].getVoltages(c)) * att2 + offset2, -10.f, 10.f); | |||||
outputs[OUT1_OUTPUT].setChannels(channels1); | outputs[OUT1_OUTPUT].setChannels(channels1); | ||||
outputs[OUT2_OUTPUT].setChannels(channels2); | outputs[OUT2_OUTPUT].setChannels(channels2); | ||||
for (int c = 0; c < channels1; c += 4) out1[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c)); | |||||
for (int c = 0; c < channels2; c += 4) out2[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); | |||||
float light1 = outputs[OUT1_OUTPUT].getVoltageSum()/channels1; | |||||
float light2 = outputs[OUT2_OUTPUT].getVoltageSum()/channels2; | |||||
if(channels1==1) { | |||||
lights[OUT1_LIGHT ].setSmoothBrightness(light1 / 5.f, args.sampleTime); | |||||
lights[OUT1_LIGHT+1].setSmoothBrightness(-light1 / 5.f, args.sampleTime); | |||||
lights[OUT1_LIGHT+2].setBrightness(0.0f); | |||||
} else { | |||||
lights[OUT1_LIGHT ].setBrightness(0.0f); | |||||
lights[OUT1_LIGHT+1].setBrightness(0.0f); | |||||
lights[OUT1_LIGHT+2].setBrightness(10.0f); | |||||
} | |||||
if(channels2==1) { | |||||
lights[OUT2_LIGHT ].setSmoothBrightness(light2 / 5.f, args.sampleTime); | |||||
lights[OUT2_LIGHT+1].setSmoothBrightness(-light2 / 5.f, args.sampleTime); | |||||
lights[OUT2_LIGHT+2].setBrightness(0.0f); | |||||
} else { | |||||
lights[OUT2_LIGHT ].setBrightness(0.0f); | |||||
lights[OUT2_LIGHT+1].setBrightness(0.0f); | |||||
lights[OUT2_LIGHT+2].setBrightness(10.0f); | |||||
for (int c = 0; c < channels1; c += 4) { | |||||
out1[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c)); | |||||
} | |||||
for (int c = 0; c < channels2; c += 4) { | |||||
out2[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); | |||||
} | } | ||||
float light1 = outputs[OUT1_OUTPUT].getVoltageSum() / channels1; | |||||
float light2 = outputs[OUT2_OUTPUT].getVoltageSum() / channels2; | |||||
if (channels1 == 1) { | |||||
lights[OUT1_LIGHT + 0].setSmoothBrightness(light1 / 5.f, args.sampleTime); | |||||
lights[OUT1_LIGHT + 1].setSmoothBrightness(-light1 / 5.f, args.sampleTime); | |||||
lights[OUT1_LIGHT + 2].setBrightness(0.0f); | |||||
} | |||||
else { | |||||
lights[OUT1_LIGHT + 0].setBrightness(0.0f); | |||||
lights[OUT1_LIGHT + 1].setBrightness(0.0f); | |||||
lights[OUT1_LIGHT + 2].setBrightness(10.0f); | |||||
} | |||||
if (channels2 == 1) { | |||||
lights[OUT2_LIGHT + 0].setSmoothBrightness(light2 / 5.f, args.sampleTime); | |||||
lights[OUT2_LIGHT + 1].setSmoothBrightness(-light2 / 5.f, args.sampleTime); | |||||
lights[OUT2_LIGHT + 2].setBrightness(0.0f); | |||||
} | |||||
else { | |||||
lights[OUT2_LIGHT + 0].setBrightness(0.0f); | |||||
lights[OUT2_LIGHT + 1].setBrightness(0.0f); | |||||
lights[OUT2_LIGHT + 2].setBrightness(10.0f); | |||||
} | |||||
} | } | ||||
}; | }; | ||||
@@ -49,21 +49,21 @@ struct EvenVCO : Module { | |||||
configParam(OCTAVE_PARAM, -5.0, 4.0, 0.0, "Octave", "'", 0.5); | configParam(OCTAVE_PARAM, -5.0, 4.0, 0.0, "Octave", "'", 0.5); | ||||
configParam(TUNE_PARAM, -7.0, 7.0, 0.0, "Tune", " semitones"); | configParam(TUNE_PARAM, -7.0, 7.0, 0.0, "Tune", " semitones"); | ||||
configParam(PWM_PARAM, -1.0, 1.0, 0.0, "Pulse width"); | configParam(PWM_PARAM, -1.0, 1.0, 0.0, "Pulse width"); | ||||
for(int i=0; i<4; i++) { | |||||
for (int i = 0; i < 4; i++) { | |||||
phase[i] = simd::float_4(0.0f); | phase[i] = simd::float_4(0.0f); | ||||
tri[i] = simd::float_4(0.0f); | tri[i] = simd::float_4(0.0f); | ||||
} | } | ||||
for(int c=0; c<PORT_MAX_CHANNELS; c++) halfPhase[c] = false; | |||||
for (int c = 0; c < PORT_MAX_CHANNELS; c++) | |||||
halfPhase[c] = false; | |||||
} | } | ||||
void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
simd::float_4 pitch[4]; | |||||
simd::float_4 pitch[4]; | |||||
simd::float_4 pitch_1[4]; | simd::float_4 pitch_1[4]; | ||||
simd::float_4 pitch_2[4]; | simd::float_4 pitch_2[4]; | ||||
simd::float_4 pitch_fm[4]; | simd::float_4 pitch_fm[4]; | ||||
simd::float_4 freq[4]; | |||||
simd::float_4 freq[4]; | |||||
simd::float_4 pw[4]; | simd::float_4 pw[4]; | ||||
simd::float_4 pwm[4]; | simd::float_4 pwm[4]; | ||||
simd::float_4 deltaPhase[4]; | simd::float_4 deltaPhase[4]; | ||||
@@ -82,26 +82,30 @@ struct EvenVCO : Module { | |||||
// Compute frequency, pitch is 1V/oct | // Compute frequency, pitch is 1V/oct | ||||
for(int c=0; c<channels; c+=4) pitch[c/4] = simd::float_4(pitch_0); | |||||
for (int c = 0; c < channels; c += 4) | |||||
pitch[c / 4] = simd::float_4(pitch_0); | |||||
if(inputs[PITCH1_INPUT].isConnected()) { | |||||
if (inputs[PITCH1_INPUT].isConnected()) { | |||||
load_input(inputs[PITCH1_INPUT], pitch_1, channels_pitch1); | load_input(inputs[PITCH1_INPUT], pitch_1, channels_pitch1); | ||||
for(int c=0; c<channels_pitch1; c+=4) pitch[c/4] += pitch_1[c/4]; | |||||
for (int c = 0; c < channels_pitch1; c += 4) | |||||
pitch[c / 4] += pitch_1[c / 4]; | |||||
} | } | ||||
if(inputs[PITCH2_INPUT].isConnected()) { | |||||
if (inputs[PITCH2_INPUT].isConnected()) { | |||||
load_input(inputs[PITCH2_INPUT], pitch_2, channels_pitch2); | load_input(inputs[PITCH2_INPUT], pitch_2, channels_pitch2); | ||||
for(int c=0; c<channels_pitch2; c+=4) pitch[c/4] += pitch_2[c/4]; | |||||
for (int c = 0; c < channels_pitch2; c += 4) | |||||
pitch[c / 4] += pitch_2[c / 4]; | |||||
} | } | ||||
if(inputs[FM_INPUT].isConnected()) { | |||||
if (inputs[FM_INPUT].isConnected()) { | |||||
load_input(inputs[FM_INPUT], pitch_fm, channels_fm); | load_input(inputs[FM_INPUT], pitch_fm, channels_fm); | ||||
for(int c=0; c<channels_fm; c+=4) pitch[c/4] += pitch_fm[c/4] / 4.f; | |||||
for (int c = 0; c < channels_fm; c += 4) | |||||
pitch[c / 4] += pitch_fm[c / 4] / 4.f; | |||||
} | } | ||||
for(int c=0; c<channels; c+=4) { | |||||
freq[c/4] = dsp::FREQ_C4 * simd::pow(2.f, pitch[c/4]); | |||||
freq[c/4] = clamp(freq[c/4], 0.f, 20000.f); | |||||
for (int c = 0; c < channels; c += 4) { | |||||
freq[c / 4] = dsp::FREQ_C4 * simd::pow(2.f, pitch[c / 4]); | |||||
freq[c / 4] = clamp(freq[c / 4], 0.f, 20000.f); | |||||
} | } | ||||
@@ -109,46 +113,48 @@ struct EvenVCO : Module { | |||||
float pw_0 = params[PWM_PARAM].getValue(); | float pw_0 = params[PWM_PARAM].getValue(); | ||||
for(int c=0; c<channels; c+=4) pw[c/4] = simd::float_4(pw_0); | |||||
if(inputs[PWM_INPUT].isConnected()) { | |||||
for (int c = 0; c < channels; c += 4) | |||||
pw[c / 4] = simd::float_4(pw_0); | |||||
if (inputs[PWM_INPUT].isConnected()) { | |||||
load_input(inputs[PWM_INPUT], pwm, channels_pwm); | load_input(inputs[PWM_INPUT], pwm, channels_pwm); | ||||
for(int c=0; c<channels_pwm; c+=4) pw[c/4] += pwm[c/4] / 5.f; | |||||
for (int c = 0; c < channels_pwm; c += 4) | |||||
pw[c / 4] += pwm[c / 4] / 5.f; | |||||
} | } | ||||
const simd::float_4 minPw_4 = simd::float_4(0.05f); | const simd::float_4 minPw_4 = simd::float_4(0.05f); | ||||
const simd::float_4 m_one_4 = simd::float_4(-1.0f); | const simd::float_4 m_one_4 = simd::float_4(-1.0f); | ||||
const simd::float_4 one_4 = simd::float_4(1.0f); | const simd::float_4 one_4 = simd::float_4(1.0f); | ||||
for(int c=0; c<channels; c+=4) { | |||||
pw[c/4] = rescale(clamp(pw[c/4], m_one_4, one_4), m_one_4, one_4, minPw_4, one_4 - minPw_4); | |||||
for (int c = 0; c < channels; c += 4) { | |||||
pw[c / 4] = rescale(clamp(pw[c / 4], m_one_4, one_4), m_one_4, one_4, minPw_4, one_4 - minPw_4); | |||||
// Advance phase | // Advance phase | ||||
deltaPhase[c/4] = clamp(freq[c/4] * args.sampleTime, simd::float_4(1e-6f), simd::float_4(0.5f)); | |||||
oldPhase[c/4] = phase[c/4]; | |||||
phase[c/4] += deltaPhase[c/4]; | |||||
deltaPhase[c / 4] = clamp(freq[c / 4] * args.sampleTime, simd::float_4(1e-6f), simd::float_4(0.5f)); | |||||
oldPhase[c / 4] = phase[c / 4]; | |||||
phase[c / 4] += deltaPhase[c / 4]; | |||||
} | } | ||||
// the next block can't be done with SIMD instructions: | // the next block can't be done with SIMD instructions: | ||||
for(int c=0; c<channels; c++) { | |||||
for (int c = 0; c < channels; c++) { | |||||
if (oldPhase[c/4].s[c%4] < 0.5 && phase[c/4].s[c%4] >= 0.5) { | |||||
float crossing = -(phase[c/4].s[c%4] - 0.5) / deltaPhase[c/4].s[c%4]; | |||||
if (oldPhase[c / 4].s[c % 4] < 0.5 && phase[c / 4].s[c % 4] >= 0.5) { | |||||
float crossing = -(phase[c / 4].s[c % 4] - 0.5) / deltaPhase[c / 4].s[c % 4]; | |||||
triSquareMinBlep[c].insertDiscontinuity(crossing, 2.f); | triSquareMinBlep[c].insertDiscontinuity(crossing, 2.f); | ||||
doubleSawMinBlep[c].insertDiscontinuity(crossing, -2.f); | doubleSawMinBlep[c].insertDiscontinuity(crossing, -2.f); | ||||
} | } | ||||
if (!halfPhase[c] && phase[c/4].s[c%4] >= pw[c/4].s[c%4]) { | |||||
float crossing = -(phase[c/4].s[c%4] - pw[c/4].s[c%4]) / deltaPhase[c/4].s[c%4]; | |||||
if (!halfPhase[c] && phase[c / 4].s[c % 4] >= pw[c / 4].s[c % 4]) { | |||||
float crossing = -(phase[c / 4].s[c % 4] - pw[c / 4].s[c % 4]) / deltaPhase[c / 4].s[c % 4]; | |||||
squareMinBlep[c].insertDiscontinuity(crossing, 2.f); | squareMinBlep[c].insertDiscontinuity(crossing, 2.f); | ||||
halfPhase[c] = true; | halfPhase[c] = true; | ||||
} | |||||
} | |||||
// Reset phase if at end of cycle | // Reset phase if at end of cycle | ||||
if (phase[c/4].s[c%4] >= 1.f) { | |||||
phase[c/4].s[c%4] -= 1.f; | |||||
float crossing = -phase[c/4].s[c%4] / deltaPhase[c/4].s[c%4]; | |||||
if (phase[c / 4].s[c % 4] >= 1.f) { | |||||
phase[c / 4].s[c % 4] -= 1.f; | |||||
float crossing = -phase[c / 4].s[c % 4] / deltaPhase[c / 4].s[c % 4]; | |||||
triSquareMinBlep[c].insertDiscontinuity(crossing, -2.f); | triSquareMinBlep[c].insertDiscontinuity(crossing, -2.f); | ||||
doubleSawMinBlep[c].insertDiscontinuity(crossing, -2.f); | doubleSawMinBlep[c].insertDiscontinuity(crossing, -2.f); | ||||
squareMinBlep[c].insertDiscontinuity(crossing, -2.f); | squareMinBlep[c].insertDiscontinuity(crossing, -2.f); | ||||
@@ -171,11 +177,11 @@ struct EvenVCO : Module { | |||||
simd::float_4 square[4]; | simd::float_4 square[4]; | ||||
simd::float_4 triOut[4]; | simd::float_4 triOut[4]; | ||||
for(int c=0; c<channels; c++) { | |||||
triSquareMinBlepOut[c/4].s[c%4] = triSquareMinBlep[c].process(); | |||||
doubleSawMinBlepOut[c/4].s[c%4] = doubleSawMinBlep[c].process(); | |||||
sawMinBlepOut[c/4].s[c%4] = sawMinBlep[c].process(); | |||||
squareMinBlepOut[c/4].s[c%4] = squareMinBlep[c].process(); | |||||
for (int c = 0; c < channels; c++) { | |||||
triSquareMinBlepOut[c / 4].s[c % 4] = triSquareMinBlep[c].process(); | |||||
doubleSawMinBlepOut[c / 4].s[c % 4] = doubleSawMinBlep[c].process(); | |||||
sawMinBlepOut[c / 4].s[c % 4] = sawMinBlep[c].process(); | |||||
squareMinBlepOut[c / 4].s[c % 4] = squareMinBlep[c].process(); | |||||
} | } | ||||
// Outputs | // Outputs | ||||
@@ -186,40 +192,39 @@ struct EvenVCO : Module { | |||||
outputs[SAW_OUTPUT].setChannels(channels); | outputs[SAW_OUTPUT].setChannels(channels); | ||||
outputs[SQUARE_OUTPUT].setChannels(channels); | outputs[SQUARE_OUTPUT].setChannels(channels); | ||||
for(int c=0; c<channels; c+=4) { | |||||
triSquare[c/4] = simd::ifelse( (phase[c/4] < 0.5f*one_4), m_one_4, one_4); | |||||
triSquare[c/4] += triSquareMinBlepOut[c/4]; | |||||
for (int c = 0; c < channels; c += 4) { | |||||
triSquare[c / 4] = simd::ifelse((phase[c / 4] < 0.5f * one_4), m_one_4, one_4); | |||||
triSquare[c / 4] += triSquareMinBlepOut[c / 4]; | |||||
// Integrate square for triangle | // Integrate square for triangle | ||||
tri[c/4] += (4.f * triSquare[c/4]) * (freq[c/4] * args.sampleTime); | |||||
tri[c/4] *= (1.f - 40.f * args.sampleTime); | |||||
triOut[c/4] = 5.f * tri[c/4]; | |||||
tri[c / 4] += (4.f * triSquare[c / 4]) * (freq[c / 4] * args.sampleTime); | |||||
tri[c / 4] *= (1.f - 40.f * args.sampleTime); | |||||
triOut[c / 4] = 5.f * tri[c / 4]; | |||||
sine[c / 4] = 5.f * simd::cos(2 * M_PI * phase[c / 4]); | |||||
sine[c/4] = 5.f * simd::cos(2*M_PI * phase[c/4]); | |||||
doubleSaw[c/4] = simd::ifelse( (phase[c/4] < 0.5), (-1.f + 4.f*phase[c/4]), (-1.f + 4.f*(phase[c/4] - 0.5f))); | |||||
doubleSaw[c/4] += doubleSawMinBlepOut[c/4]; | |||||
doubleSaw[c/4] *= 5.f; | |||||
doubleSaw[c / 4] = simd::ifelse((phase[c / 4] < 0.5), (-1.f + 4.f * phase[c / 4]), (-1.f + 4.f * (phase[c / 4] - 0.5f))); | |||||
doubleSaw[c / 4] += doubleSawMinBlepOut[c / 4]; | |||||
doubleSaw[c / 4] *= 5.f; | |||||
even[c/4] = 0.55 * (doubleSaw[c/4] + 1.27 * sine[c/4]); | |||||
saw[c/4] = -1.f + 2.f*phase[c/4]; | |||||
saw[c/4] += sawMinBlepOut[c/4]; | |||||
saw[c/4] *= 5.f; | |||||
even[c / 4] = 0.55 * (doubleSaw[c / 4] + 1.27 * sine[c / 4]); | |||||
saw[c / 4] = -1.f + 2.f * phase[c / 4]; | |||||
saw[c / 4] += sawMinBlepOut[c / 4]; | |||||
saw[c / 4] *= 5.f; | |||||
square[c/4] = simd::ifelse( (phase[c/4] < pw[c/4]), m_one_4, one_4) ; | |||||
square[c/4] += squareMinBlepOut[c/4]; | |||||
square[c/4] *= 5.f; | |||||
square[c / 4] = simd::ifelse((phase[c / 4] < pw[c / 4]), m_one_4, one_4) ; | |||||
square[c / 4] += squareMinBlepOut[c / 4]; | |||||
square[c / 4] *= 5.f; | |||||
// Set outputs | // Set outputs | ||||
triOut[c/4].store(outputs[TRI_OUTPUT].getVoltages(c)); | |||||
sine[c/4].store(outputs[SINE_OUTPUT].getVoltages(c)); | |||||
even[c/4].store(outputs[EVEN_OUTPUT].getVoltages(c)); | |||||
saw[c/4].store(outputs[SAW_OUTPUT].getVoltages(c)); | |||||
square[c/4].store(outputs[SQUARE_OUTPUT].getVoltages(c)); | |||||
triOut[c / 4].store(outputs[TRI_OUTPUT].getVoltages(c)); | |||||
sine[c / 4].store(outputs[SINE_OUTPUT].getVoltages(c)); | |||||
even[c / 4].store(outputs[EVEN_OUTPUT].getVoltages(c)); | |||||
saw[c / 4].store(outputs[SAW_OUTPUT].getVoltages(c)); | |||||
square[c / 4].store(outputs[SQUARE_OUTPUT].getVoltages(c)); | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
@@ -232,8 +237,8 @@ struct EvenVCOWidget : ModuleWidget { | |||||
addChild(createWidget<Knurlie>(Vec(15, 0))); | addChild(createWidget<Knurlie>(Vec(15, 0))); | ||||
addChild(createWidget<Knurlie>(Vec(15, 365))); | addChild(createWidget<Knurlie>(Vec(15, 365))); | ||||
addChild(createWidget<Knurlie>(Vec(15*6, 0))); | |||||
addChild(createWidget<Knurlie>(Vec(15*6, 365))); | |||||
addChild(createWidget<Knurlie>(Vec(15 * 6, 0))); | |||||
addChild(createWidget<Knurlie>(Vec(15 * 6, 365))); | |||||
addParam(createParam<BefacoBigSnapKnob>(Vec(22, 32), module, EvenVCO::OCTAVE_PARAM)); | addParam(createParam<BefacoBigSnapKnob>(Vec(22, 32), module, EvenVCO::OCTAVE_PARAM)); | ||||
addParam(createParam<BefacoTinyKnob>(Vec(73, 131), module, EvenVCO::TUNE_PARAM)); | addParam(createParam<BefacoTinyKnob>(Vec(73, 131), module, EvenVCO::TUNE_PARAM)); | ||||
@@ -2,7 +2,6 @@ | |||||
#include "simd_input.hpp" | #include "simd_input.hpp" | ||||
struct Mixer : Module { | struct Mixer : Module { | ||||
enum ParamIds { | enum ParamIds { | ||||
CH1_PARAM, | CH1_PARAM, | ||||
@@ -30,21 +29,15 @@ struct Mixer : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
simd::float_4 minus_one; | |||||
Mixer() { | Mixer() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
configParam(CH1_PARAM, 0.0, 1.0, 0.0, "Ch 1 level", "%", 0, 100); | configParam(CH1_PARAM, 0.0, 1.0, 0.0, "Ch 1 level", "%", 0, 100); | ||||
configParam(CH2_PARAM, 0.0, 1.0, 0.0, "Ch 2 level", "%", 0, 100); | configParam(CH2_PARAM, 0.0, 1.0, 0.0, "Ch 2 level", "%", 0, 100); | ||||
configParam(CH3_PARAM, 0.0, 1.0, 0.0, "Ch 3 level", "%", 0, 100); | configParam(CH3_PARAM, 0.0, 1.0, 0.0, "Ch 3 level", "%", 0, 100); | ||||
configParam(CH4_PARAM, 0.0, 1.0, 0.0, "Ch 4 level", "%", 0, 100); | configParam(CH4_PARAM, 0.0, 1.0, 0.0, "Ch 4 level", "%", 0, 100); | ||||
minus_one = simd::float_4(-1.0f); | |||||
} | } | ||||
void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
int channels1 = inputs[IN1_INPUT].getChannels(); | int channels1 = inputs[IN1_INPUT].getChannels(); | ||||
int channels2 = inputs[IN2_INPUT].getChannels(); | int channels2 = inputs[IN2_INPUT].getChannels(); | ||||
int channels3 = inputs[IN3_INPUT].getChannels(); | int channels3 = inputs[IN3_INPUT].getChannels(); | ||||
@@ -55,66 +48,68 @@ struct Mixer : Module { | |||||
out_channels = std::max(out_channels, channels2); | out_channels = std::max(out_channels, channels2); | ||||
out_channels = std::max(out_channels, channels3); | out_channels = std::max(out_channels, channels3); | ||||
out_channels = std::max(out_channels, channels4); | out_channels = std::max(out_channels, channels4); | ||||
simd::float_4 mult1 = simd::float_4(params[CH1_PARAM].getValue()); | simd::float_4 mult1 = simd::float_4(params[CH1_PARAM].getValue()); | ||||
simd::float_4 mult2 = simd::float_4(params[CH2_PARAM].getValue()); | simd::float_4 mult2 = simd::float_4(params[CH2_PARAM].getValue()); | ||||
simd::float_4 mult3 = simd::float_4(params[CH3_PARAM].getValue()); | simd::float_4 mult3 = simd::float_4(params[CH3_PARAM].getValue()); | ||||
simd::float_4 mult4 = simd::float_4(params[CH4_PARAM].getValue()); | simd::float_4 mult4 = simd::float_4(params[CH4_PARAM].getValue()); | ||||
simd::float_4 out[4]; | |||||
simd::float_4 out[4]; | |||||
memset(out, 0, sizeof(out)); | |||||
std::memset(out, 0, sizeof(out)); | |||||
if(inputs[IN1_INPUT].isConnected()) { | |||||
for(int c=0; c<channels1; c+=4) out[c/4] += simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * mult1; | |||||
if (inputs[IN1_INPUT].isConnected()) { | |||||
for (int c = 0; c < channels1; c += 4) | |||||
out[c / 4] += simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * mult1; | |||||
} | } | ||||
if(inputs[IN2_INPUT].isConnected()) { | |||||
for(int c=0; c<channels2; c+=4) out[c/4] += simd::float_4::load(inputs[IN2_INPUT].getVoltages(c)) * mult2; | |||||
if (inputs[IN2_INPUT].isConnected()) { | |||||
for (int c = 0; c < channels2; c += 4) | |||||
out[c / 4] += simd::float_4::load(inputs[IN2_INPUT].getVoltages(c)) * mult2; | |||||
} | } | ||||
if(inputs[IN3_INPUT].isConnected()) { | |||||
for(int c=0; c<channels3; c+=4) out[c/4] += simd::float_4::load(inputs[IN3_INPUT].getVoltages(c)) * mult3; | |||||
if (inputs[IN3_INPUT].isConnected()) { | |||||
for (int c = 0; c < channels3; c += 4) | |||||
out[c / 4] += simd::float_4::load(inputs[IN3_INPUT].getVoltages(c)) * mult3; | |||||
} | } | ||||
if(inputs[IN4_INPUT].isConnected()) { | |||||
for(int c=0; c<channels4; c+=4) out[c/4] += simd::float_4::load(inputs[IN4_INPUT].getVoltages(c)) * mult4; | |||||
if (inputs[IN4_INPUT].isConnected()) { | |||||
for (int c = 0; c < channels4; c += 4) | |||||
out[c / 4] += simd::float_4::load(inputs[IN4_INPUT].getVoltages(c)) * mult4; | |||||
} | } | ||||
outputs[OUT1_OUTPUT].setChannels(out_channels); | outputs[OUT1_OUTPUT].setChannels(out_channels); | ||||
outputs[OUT2_OUTPUT].setChannels(out_channels); | outputs[OUT2_OUTPUT].setChannels(out_channels); | ||||
for(int c=0; c<out_channels; c+=4) { | |||||
for (int c = 0; c < out_channels; c += 4) { | |||||
out[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c)); | out[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c)); | ||||
out[c / 4] *= minus_one; | |||||
out[c / 4] *= -1.f; | |||||
out[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); | out[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); | ||||
} | } | ||||
if(out_channels==1) { | |||||
if (out_channels == 1) { | |||||
float light = outputs[OUT1_OUTPUT].getVoltage(); | float light = outputs[OUT1_OUTPUT].getVoltage(); | ||||
lights[OUT_POS_LIGHT].setSmoothBrightness(light / 5.f, args.sampleTime); | lights[OUT_POS_LIGHT].setSmoothBrightness(light / 5.f, args.sampleTime); | ||||
lights[OUT_NEG_LIGHT].setSmoothBrightness(-light / 5.f, args.sampleTime); | lights[OUT_NEG_LIGHT].setSmoothBrightness(-light / 5.f, args.sampleTime); | ||||
} else | |||||
{ | |||||
} | |||||
else { | |||||
float light = 0.0f; | float light = 0.0f; | ||||
for(int c=0; c<out_channels; c++) { | |||||
for (int c = 0; c < out_channels; c++) { | |||||
float tmp = outputs[OUT1_OUTPUT].getVoltage(c); | float tmp = outputs[OUT1_OUTPUT].getVoltage(c); | ||||
light += tmp*tmp; | |||||
light += tmp * tmp; | |||||
} | } | ||||
light = sqrt(light); | |||||
light = std::sqrt(light); | |||||
lights[OUT_POS_LIGHT].setBrightness(0.0f); | lights[OUT_POS_LIGHT].setBrightness(0.0f); | ||||
lights[OUT_NEG_LIGHT].setBrightness(0.0f); | lights[OUT_NEG_LIGHT].setBrightness(0.0f); | ||||
lights[OUT_BLUE_LIGHT].setSmoothBrightness(light / 5.f, args.sampleTime); | lights[OUT_BLUE_LIGHT].setSmoothBrightness(light / 5.f, args.sampleTime); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
struct MixerWidget : ModuleWidget { | struct MixerWidget : ModuleWidget { | ||||
MixerWidget(Mixer *module) { | MixerWidget(Mixer *module) { | ||||
setModule(module); | setModule(module); | ||||
@@ -5,28 +5,28 @@ | |||||
/** When triggered, holds a high value for a specified time before going low again */ | /** When triggered, holds a high value for a specified time before going low again */ | ||||
struct PulseGenerator_4 { | struct PulseGenerator_4 { | ||||
simd::float_4 remaining = simd::float_4::zero(); | |||||
/** Immediately disables the pulse */ | |||||
void reset() { | |||||
remaining = simd::float_4::zero(); | |||||
} | |||||
simd::float_4 remaining = simd::float_4::zero(); | |||||
/** Advances the state by `deltaTime`. Returns whether the pulse is in the HIGH state. */ | |||||
inline simd::float_4 process(float deltaTime) { | |||||
/** Immediately disables the pulse */ | |||||
void reset() { | |||||
remaining = simd::float_4::zero(); | |||||
} | |||||
simd::float_4 mask = (remaining > simd::float_4::zero()); | |||||
/** Advances the state by `deltaTime`. Returns whether the pulse is in the HIGH state. */ | |||||
inline simd::float_4 process(float deltaTime) { | |||||
remaining -= ifelse(mask, simd::float_4(deltaTime), simd::float_4::zero()); | |||||
return ifelse(mask, simd::float_4::mask(), simd::float_4::zero()); | |||||
} | |||||
simd::float_4 mask = (remaining > simd::float_4::zero()); | |||||
/** Begins a trigger with the given `duration`. */ | |||||
inline void trigger(simd::float_4 mask, float duration = 1e-3f) { | |||||
// Keep the previous pulse if the existing pulse will be held longer than the currently requested one. | |||||
simd::float_4 duration_4 = simd::float_4(duration); | |||||
remaining = ifelse( mask&(duration_4>remaining), duration_4, remaining); | |||||
} | |||||
remaining -= ifelse(mask, simd::float_4(deltaTime), simd::float_4::zero()); | |||||
return ifelse(mask, simd::float_4::mask(), simd::float_4::zero()); | |||||
} | |||||
/** Begins a trigger with the given `duration`. */ | |||||
inline void trigger(simd::float_4 mask, float duration = 1e-3f) { | |||||
// Keep the previous pulse if the existing pulse will be held longer than the currently requested one. | |||||
simd::float_4 duration_4 = simd::float_4(duration); | |||||
remaining = ifelse(mask & (duration_4 > remaining), duration_4, remaining); | |||||
} | |||||
}; | }; | ||||
@@ -81,7 +81,7 @@ struct Rampage : Module { | |||||
dsp::TSchmittTrigger<simd::float_4> trigger_4[2][4]; | dsp::TSchmittTrigger<simd::float_4> trigger_4[2][4]; | ||||
PulseGenerator_4 endOfCyclePulse[2][4]; | PulseGenerator_4 endOfCyclePulse[2][4]; | ||||
// ChannelMask channelMask; | |||||
// ChannelMask channelMask; | |||||
Rampage() { | Rampage() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
@@ -99,29 +99,28 @@ struct Rampage : Module { | |||||
configParam(CYCLE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 cycle"); | configParam(CYCLE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 cycle"); | ||||
configParam(BALANCE_PARAM, 0.0, 1.0, 0.5, "Balance"); | configParam(BALANCE_PARAM, 0.0, 1.0, 0.5, "Balance"); | ||||
memset(out, 0, sizeof(out)); | |||||
memset(gate, 0, sizeof(gate)); | |||||
std::memset(out, 0, sizeof(out)); | |||||
std::memset(gate, 0, sizeof(gate)); | |||||
} | } | ||||
void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
int channels_in[2]; | int channels_in[2]; | ||||
int channels_trig[2]; | int channels_trig[2]; | ||||
int channels[2]; | int channels[2]; | ||||
// determine number of channels: | |||||
// determine number of channels: | |||||
for (int part = 0; part < 2; part++) { | |||||
for (int part=0; part<2; part++) { | |||||
channels_in[part] = inputs[IN_A_INPUT+part].getChannels(); | |||||
channels_trig[part] = inputs[TRIGG_A_INPUT+part].getChannels(); | |||||
channels_in[part] = inputs[IN_A_INPUT + part].getChannels(); | |||||
channels_trig[part] = inputs[TRIGG_A_INPUT + part].getChannels(); | |||||
channels[part] = std::max(channels_in[part], channels_trig[part]); | channels[part] = std::max(channels_in[part], channels_trig[part]); | ||||
channels[part] = std::max(1, channels[part]); | channels[part] = std::max(1, channels[part]); | ||||
outputs[OUT_A_OUTPUT+part].setChannels(channels[part]); | |||||
outputs[RISING_A_OUTPUT+part].setChannels(channels[part]); | |||||
outputs[FALLING_A_OUTPUT+part].setChannels(channels[part]); | |||||
outputs[EOC_A_OUTPUT+part].setChannels(channels[part]); | |||||
outputs[OUT_A_OUTPUT + part].setChannels(channels[part]); | |||||
outputs[RISING_A_OUTPUT + part].setChannels(channels[part]); | |||||
outputs[FALLING_A_OUTPUT + part].setChannels(channels[part]); | |||||
outputs[EOC_A_OUTPUT + part].setChannels(channels[part]); | |||||
} | } | ||||
int channels_max = std::max(channels[0], channels[1]); | int channels_max = std::max(channels[0], channels[1]); | ||||
@@ -145,9 +144,15 @@ struct Rampage : Module { | |||||
float shape = params[SHAPE_A_PARAM + part].getValue(); | float shape = params[SHAPE_A_PARAM + part].getValue(); | ||||
float minTime; | float minTime; | ||||
switch ((int) params[RANGE_A_PARAM + part].getValue()) { | switch ((int) params[RANGE_A_PARAM + part].getValue()) { | ||||
case 0: minTime = 1e-2; break; | |||||
case 1: minTime = 1e-3; break; | |||||
default: minTime = 1e-1; break; | |||||
case 0: | |||||
minTime = 1e-2; | |||||
break; | |||||
case 1: | |||||
minTime = 1e-3; | |||||
break; | |||||
default: | |||||
minTime = 1e-1; | |||||
break; | |||||
} | } | ||||
simd::float_4 param_rise = simd::float_4(params[RISE_A_PARAM + part].getValue() * 10.0f); | simd::float_4 param_rise = simd::float_4(params[RISE_A_PARAM + part].getValue() * 10.0f); | ||||
@@ -155,115 +160,117 @@ struct Rampage : Module { | |||||
simd::float_4 param_trig = simd::float_4(params[TRIGG_A_PARAM + part].getValue() * 20.0f); | simd::float_4 param_trig = simd::float_4(params[TRIGG_A_PARAM + part].getValue() * 20.0f); | ||||
simd::float_4 param_cycle = simd::float_4(params[CYCLE_A_PARAM + part].getValue() * 10.0f); | simd::float_4 param_cycle = simd::float_4(params[CYCLE_A_PARAM + part].getValue() * 10.0f); | ||||
for(int c=0; c<channels[part]; c+=4) { | |||||
riseCV[c/4] = param_rise; | |||||
fallCV[c/4] = param_fall; | |||||
cycle[c/4] = param_cycle; | |||||
in_trig[c/4] = param_trig; | |||||
for (int c = 0; c < channels[part]; c += 4) { | |||||
riseCV[c / 4] = param_rise; | |||||
fallCV[c / 4] = param_fall; | |||||
cycle[c / 4] = param_cycle; | |||||
in_trig[c / 4] = param_trig; | |||||
} | } | ||||
// read inputs: | // read inputs: | ||||
if(inputs[IN_A_INPUT + part].isConnected()) { | |||||
if (inputs[IN_A_INPUT + part].isConnected()) { | |||||
load_input(inputs[IN_A_INPUT + part], in, channels_in[part]); | load_input(inputs[IN_A_INPUT + part], in, channels_in[part]); | ||||
// channelMask.apply_all(in, channels_in[part]); | // channelMask.apply_all(in, channels_in[part]); | ||||
} else { | |||||
memset(in, 0, sizeof(in)); | |||||
} | |||||
else { | |||||
std::memset(in, 0, sizeof(in)); | |||||
} | } | ||||
if(inputs[TRIGG_A_INPUT + part].isConnected()) { | |||||
if (inputs[TRIGG_A_INPUT + part].isConnected()) { | |||||
add_input(inputs[TRIGG_A_INPUT + part], in_trig, channels_trig[part]); | add_input(inputs[TRIGG_A_INPUT + part], in_trig, channels_trig[part]); | ||||
// channelMask.apply_all(in_trig, channels_trig[part]); | // channelMask.apply_all(in_trig, channels_trig[part]); | ||||
} | |||||
} | |||||
if(inputs[EXP_CV_A_INPUT + part].isConnected()) { | |||||
if (inputs[EXP_CV_A_INPUT + part].isConnected()) { | |||||
load_input(inputs[EXP_CV_A_INPUT + part], expCV, channels[part]); | load_input(inputs[EXP_CV_A_INPUT + part], expCV, channels[part]); | ||||
for(int c=0; c<channels[part]; c+=4) { | |||||
riseCV[c/4] -= expCV[c/4]; | |||||
fallCV[c/4] -= expCV[c/4]; | |||||
for (int c = 0; c < channels[part]; c += 4) { | |||||
riseCV[c / 4] -= expCV[c / 4]; | |||||
fallCV[c / 4] -= expCV[c / 4]; | |||||
} | } | ||||
} | } | ||||
add_input(inputs[RISE_CV_A_INPUT + part], riseCV, channels[part]); | add_input(inputs[RISE_CV_A_INPUT + part], riseCV, channels[part]); | ||||
add_input(inputs[FALL_CV_A_INPUT + part], fallCV, channels[part]); | |||||
add_input(inputs[CYCLE_A_INPUT+part], cycle, channels[part]); | |||||
add_input(inputs[FALL_CV_A_INPUT + part], fallCV, channels[part]); | |||||
add_input(inputs[CYCLE_A_INPUT + part], cycle, channels[part]); | |||||
// channelMask.apply(cycle, channels[part]); // check whether this is necessary | // channelMask.apply(cycle, channels[part]); // check whether this is necessary | ||||
// start processing: | // start processing: | ||||
for(int c=0; c<channels[part]; c+=4) { | |||||
for (int c = 0; c < channels[part]; c += 4) { | |||||
// process SchmittTriggers | // process SchmittTriggers | ||||
simd::float_4 trig_mask = trigger_4[part][c/4].process(in_trig[c/4]/2.0); | |||||
gate[part][c/4] = ifelse(trig_mask, simd::float_4::mask(), gate[part][c/4]); | |||||
in[c/4] = ifelse(gate[part][c/4], simd::float_4(10.0f), in[c/4]); | |||||
simd::float_4 trig_mask = trigger_4[part][c / 4].process(in_trig[c / 4] / 2.0); | |||||
gate[part][c / 4] = ifelse(trig_mask, simd::float_4::mask(), gate[part][c / 4]); | |||||
in[c / 4] = ifelse(gate[part][c / 4], simd::float_4(10.0f), in[c / 4]); | |||||
simd::float_4 delta = in[c/4] - out[part][c/4]; | |||||
simd::float_4 delta = in[c / 4] - out[part][c / 4]; | |||||
// rise / fall branching | // rise / fall branching | ||||
simd::float_4 delta_gt_0 = delta > simd::float_4::zero(); | simd::float_4 delta_gt_0 = delta > simd::float_4::zero(); | ||||
simd::float_4 delta_lt_0 = delta < simd::float_4::zero(); | simd::float_4 delta_lt_0 = delta < simd::float_4::zero(); | ||||
simd::float_4 delta_eq_0 = ~(delta_lt_0|delta_gt_0); | |||||
simd::float_4 delta_eq_0 = ~(delta_lt_0 | delta_gt_0); | |||||
simd::float_4 rateCV = ifelse(delta_gt_0, riseCV[c/4], simd::float_4::zero()); | |||||
rateCV = ifelse(delta_lt_0, fallCV[c/4], rateCV); | |||||
simd::float_4 rateCV = ifelse(delta_gt_0, riseCV[c / 4], simd::float_4::zero()); | |||||
rateCV = ifelse(delta_lt_0, fallCV[c / 4], rateCV); | |||||
rateCV = clamp(rateCV, simd::float_4::zero(), simd::float_4(10.0f)); | rateCV = clamp(rateCV, simd::float_4::zero(), simd::float_4(10.0f)); | ||||
simd::float_4 rate = minTime * simd::pow(2.0f, rateCV); | simd::float_4 rate = minTime * simd::pow(2.0f, rateCV); | ||||
out[part][c/4] += shapeDelta(delta, rate, shape) * args.sampleTime; | |||||
out[part][c / 4] += shapeDelta(delta, rate, shape) * args.sampleTime; | |||||
simd::float_4 rising = (in[c/4] - out[part][c/4]) > simd::float_4( 1e-3); | |||||
simd::float_4 falling = (in[c/4] - out[part][c/4]) < simd::float_4(-1e-3); | |||||
simd::float_4 end_of_cycle = simd::andnot(falling,delta_lt_0); | |||||
simd::float_4 rising = (in[c / 4] - out[part][c / 4]) > simd::float_4(1e-3); | |||||
simd::float_4 falling = (in[c / 4] - out[part][c / 4]) < simd::float_4(-1e-3); | |||||
simd::float_4 end_of_cycle = simd::andnot(falling, delta_lt_0); | |||||
endOfCyclePulse[part][c/4].trigger(end_of_cycle, 1e-3); | |||||
endOfCyclePulse[part][c / 4].trigger(end_of_cycle, 1e-3); | |||||
gate[part][c/4] = ifelse( simd::andnot(rising, delta_gt_0), simd::float_4::zero(), gate[part][c/4]); | |||||
gate[part][c/4] = ifelse( end_of_cycle & (cycle[c/4]>=simd::float_4(4.0f)), simd::float_4::mask(), gate[part][c/4] ); | |||||
gate[part][c/4] = ifelse( delta_eq_0, simd::float_4::zero(), gate[part][c/4] ); | |||||
gate[part][c / 4] = ifelse(simd::andnot(rising, delta_gt_0), simd::float_4::zero(), gate[part][c / 4]); | |||||
gate[part][c / 4] = ifelse(end_of_cycle & (cycle[c / 4] >= simd::float_4(4.0f)), simd::float_4::mask(), gate[part][c / 4]); | |||||
gate[part][c / 4] = ifelse(delta_eq_0, simd::float_4::zero(), gate[part][c / 4]); | |||||
out[part][c/4] = ifelse( rising|falling, out[part][c/4], in[c/4] ); | |||||
out[part][c / 4] = ifelse(rising | falling, out[part][c / 4], in[c / 4]); | |||||
simd::float_4 out_rising = ifelse(rising, simd::float_4(10.0f), simd::float_4::zero() ); | |||||
simd::float_4 out_falling = ifelse(falling, simd::float_4(10.0f), simd::float_4::zero() ); | |||||
simd::float_4 out_rising = ifelse(rising, simd::float_4(10.0f), simd::float_4::zero()); | |||||
simd::float_4 out_falling = ifelse(falling, simd::float_4(10.0f), simd::float_4::zero()); | |||||
simd::float_4 pulse = endOfCyclePulse[part][c/4].process(args.sampleTime); | |||||
simd::float_4 out_EOC = ifelse(pulse, simd::float_4(10.f), simd::float_4::zero() ); | |||||
simd::float_4 pulse = endOfCyclePulse[part][c / 4].process(args.sampleTime); | |||||
simd::float_4 out_EOC = ifelse(pulse, simd::float_4(10.f), simd::float_4::zero()); | |||||
out[part][c/4].store(outputs[OUT_A_OUTPUT+part].getVoltages(c)); | |||||
out[part][c / 4].store(outputs[OUT_A_OUTPUT + part].getVoltages(c)); | |||||
out_rising.store( outputs[RISING_A_OUTPUT+part].getVoltages(c)); | |||||
out_falling.store(outputs[FALLING_A_OUTPUT+part].getVoltages(c)); | |||||
out_EOC.store(outputs[EOC_A_OUTPUT+part].getVoltages(c)); | |||||
out_rising.store(outputs[RISING_A_OUTPUT + part].getVoltages(c)); | |||||
out_falling.store(outputs[FALLING_A_OUTPUT + part].getVoltages(c)); | |||||
out_EOC.store(outputs[EOC_A_OUTPUT + part].getVoltages(c)); | |||||
} // for(int c, ...) | } // for(int c, ...) | ||||
if(channels[part] == 1) { | |||||
lights[RISING_A_LIGHT + 3*part ].setSmoothBrightness(outputs[RISING_A_OUTPUT+part].getVoltage()/10.f, args.sampleTime); | |||||
lights[RISING_A_LIGHT + 3*part+1].setBrightness(0.0f); | |||||
lights[RISING_A_LIGHT + 3*part+2].setBrightness(0.0f); | |||||
lights[FALLING_A_LIGHT + 3*part ].setSmoothBrightness(outputs[FALLING_A_OUTPUT+part].getVoltage()/10.f, args.sampleTime); | |||||
lights[FALLING_A_LIGHT + 3*part+1].setBrightness(0.0f); | |||||
lights[FALLING_A_LIGHT + 3*part+2].setBrightness(0.0f); | |||||
lights[OUT_A_LIGHT + 3*part ].setSmoothBrightness(out[part][0].s[0] / 10.0, args.sampleTime); | |||||
lights[OUT_A_LIGHT + 3*part+1].setBrightness(0.0f); | |||||
lights[OUT_A_LIGHT + 3*part+2].setBrightness(0.0f); | |||||
} else { | |||||
lights[RISING_A_LIGHT + 3*part ].setBrightness(0.0f); | |||||
lights[RISING_A_LIGHT + 3*part+1].setBrightness(0.0f); | |||||
lights[RISING_A_LIGHT + 3*part+2].setBrightness(10.0f); | |||||
lights[FALLING_A_LIGHT + 3*part ].setBrightness(0.0f); | |||||
lights[FALLING_A_LIGHT + 3*part+1].setBrightness(0.0f); | |||||
lights[FALLING_A_LIGHT + 3*part+2].setBrightness(10.0f); | |||||
lights[OUT_A_LIGHT + 3*part ].setBrightness(0.0f); | |||||
lights[OUT_A_LIGHT + 3*part+1].setBrightness(0.0f); | |||||
lights[OUT_A_LIGHT + 3*part+2].setBrightness(10.0f); | |||||
if (channels[part] == 1) { | |||||
lights[RISING_A_LIGHT + 3 * part ].setSmoothBrightness(outputs[RISING_A_OUTPUT + part].getVoltage() / 10.f, args.sampleTime); | |||||
lights[RISING_A_LIGHT + 3 * part + 1].setBrightness(0.0f); | |||||
lights[RISING_A_LIGHT + 3 * part + 2].setBrightness(0.0f); | |||||
lights[FALLING_A_LIGHT + 3 * part ].setSmoothBrightness(outputs[FALLING_A_OUTPUT + part].getVoltage() / 10.f, args.sampleTime); | |||||
lights[FALLING_A_LIGHT + 3 * part + 1].setBrightness(0.0f); | |||||
lights[FALLING_A_LIGHT + 3 * part + 2].setBrightness(0.0f); | |||||
lights[OUT_A_LIGHT + 3 * part ].setSmoothBrightness(out[part][0].s[0] / 10.0, args.sampleTime); | |||||
lights[OUT_A_LIGHT + 3 * part + 1].setBrightness(0.0f); | |||||
lights[OUT_A_LIGHT + 3 * part + 2].setBrightness(0.0f); | |||||
} | |||||
else { | |||||
lights[RISING_A_LIGHT + 3 * part ].setBrightness(0.0f); | |||||
lights[RISING_A_LIGHT + 3 * part + 1].setBrightness(0.0f); | |||||
lights[RISING_A_LIGHT + 3 * part + 2].setBrightness(10.0f); | |||||
lights[FALLING_A_LIGHT + 3 * part ].setBrightness(0.0f); | |||||
lights[FALLING_A_LIGHT + 3 * part + 1].setBrightness(0.0f); | |||||
lights[FALLING_A_LIGHT + 3 * part + 2].setBrightness(10.0f); | |||||
lights[OUT_A_LIGHT + 3 * part ].setBrightness(0.0f); | |||||
lights[OUT_A_LIGHT + 3 * part + 1].setBrightness(0.0f); | |||||
lights[OUT_A_LIGHT + 3 * part + 2].setBrightness(10.0f); | |||||
} | } | ||||
} // for (int part, ... ) | } // for (int part, ... ) | ||||
@@ -272,19 +279,19 @@ struct Rampage : Module { | |||||
// Logic | // Logic | ||||
float balance = params[BALANCE_PARAM].getValue(); | float balance = params[BALANCE_PARAM].getValue(); | ||||
for(int c=0; c<channels_max; c+=4) { | |||||
for (int c = 0; c < channels_max; c += 4) { | |||||
simd::float_4 a = out[0][c/4]; | |||||
simd::float_4 b = out[1][c/4]; | |||||
simd::float_4 a = out[0][c / 4]; | |||||
simd::float_4 b = out[1][c / 4]; | |||||
if (balance < 0.5) | if (balance < 0.5) | ||||
b *= 2.0f * balance; | b *= 2.0f * balance; | ||||
else if (balance > 0.5) | else if (balance > 0.5) | ||||
a *= 2.0f * (1.0 - balance); | a *= 2.0f * (1.0 - balance); | ||||
simd::float_4 comp = ifelse( b>a, simd::float_4(10.0f), simd::float_4::zero() ); | |||||
simd::float_4 out_min = simd::fmin(a,b); | |||||
simd::float_4 out_max = simd::fmax(a,b); | |||||
simd::float_4 comp = ifelse(b > a, simd::float_4(10.0f), simd::float_4::zero()); | |||||
simd::float_4 out_min = simd::fmin(a, b); | |||||
simd::float_4 out_max = simd::fmax(a, b); | |||||
comp.store(outputs[COMPARATOR_OUTPUT].getVoltages(c)); | comp.store(outputs[COMPARATOR_OUTPUT].getVoltages(c)); | ||||
out_min.store(outputs[MIN_OUTPUT].getVoltages(c)); | out_min.store(outputs[MIN_OUTPUT].getVoltages(c)); | ||||
@@ -292,29 +299,29 @@ struct Rampage : Module { | |||||
} | } | ||||
// Lights | // Lights | ||||
if(channels_max==1) { | |||||
if (channels_max == 1) { | |||||
lights[COMPARATOR_LIGHT ].setSmoothBrightness(outputs[COMPARATOR_OUTPUT].getVoltage(), args.sampleTime); | lights[COMPARATOR_LIGHT ].setSmoothBrightness(outputs[COMPARATOR_OUTPUT].getVoltage(), args.sampleTime); | ||||
lights[COMPARATOR_LIGHT+1].setBrightness(0.0f); | |||||
lights[COMPARATOR_LIGHT+2].setBrightness(0.0f); | |||||
lights[COMPARATOR_LIGHT + 1].setBrightness(0.0f); | |||||
lights[COMPARATOR_LIGHT + 2].setBrightness(0.0f); | |||||
lights[MIN_LIGHT ].setSmoothBrightness(outputs[MIN_OUTPUT].getVoltage(), args.sampleTime); | lights[MIN_LIGHT ].setSmoothBrightness(outputs[MIN_OUTPUT].getVoltage(), args.sampleTime); | ||||
lights[MIN_LIGHT+1].setBrightness(0.0f); | |||||
lights[MIN_LIGHT+2].setBrightness(0.0f); | |||||
lights[MIN_LIGHT + 1].setBrightness(0.0f); | |||||
lights[MIN_LIGHT + 2].setBrightness(0.0f); | |||||
lights[MAX_LIGHT ].setSmoothBrightness(outputs[MAX_OUTPUT].getVoltage(), args.sampleTime); | lights[MAX_LIGHT ].setSmoothBrightness(outputs[MAX_OUTPUT].getVoltage(), args.sampleTime); | ||||
lights[MAX_LIGHT+1].setBrightness(0.0f); | |||||
lights[MAX_LIGHT+2].setBrightness(0.0f); | |||||
} else { | |||||
lights[MAX_LIGHT + 1].setBrightness(0.0f); | |||||
lights[MAX_LIGHT + 2].setBrightness(0.0f); | |||||
} | |||||
else { | |||||
lights[COMPARATOR_LIGHT ].setBrightness(0.0f); | lights[COMPARATOR_LIGHT ].setBrightness(0.0f); | ||||
lights[COMPARATOR_LIGHT+1].setBrightness(0.0f); | |||||
lights[COMPARATOR_LIGHT+2].setBrightness(10.0f); | |||||
lights[COMPARATOR_LIGHT + 1].setBrightness(0.0f); | |||||
lights[COMPARATOR_LIGHT + 2].setBrightness(10.0f); | |||||
lights[MIN_LIGHT ].setBrightness(0.0f); | lights[MIN_LIGHT ].setBrightness(0.0f); | ||||
lights[MIN_LIGHT+1].setBrightness(0.0f); | |||||
lights[MIN_LIGHT+2].setBrightness(10.0f); | |||||
lights[MIN_LIGHT + 1].setBrightness(0.0f); | |||||
lights[MIN_LIGHT + 2].setBrightness(10.0f); | |||||
lights[MAX_LIGHT ].setBrightness(0.0f); | lights[MAX_LIGHT ].setBrightness(0.0f); | ||||
lights[MAX_LIGHT+1].setBrightness(0.0f); | |||||
lights[MAX_LIGHT+2].setBrightness(10.0f); | |||||
lights[MAX_LIGHT + 1].setBrightness(0.0f); | |||||
lights[MAX_LIGHT + 2].setBrightness(10.0f); | |||||
} | } | ||||
} // end process() | |||||
} | |||||
}; | }; | ||||
@@ -326,9 +333,9 @@ struct RampageWidget : ModuleWidget { | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Rampage.svg"))); | setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Rampage.svg"))); | ||||
addChild(createWidget<Knurlie>(Vec(15, 0))); | addChild(createWidget<Knurlie>(Vec(15, 0))); | ||||
addChild(createWidget<Knurlie>(Vec(box.size.x-30, 0))); | |||||
addChild(createWidget<Knurlie>(Vec(box.size.x - 30, 0))); | |||||
addChild(createWidget<Knurlie>(Vec(15, 365))); | addChild(createWidget<Knurlie>(Vec(15, 365))); | ||||
addChild(createWidget<Knurlie>(Vec(box.size.x-30, 365))); | |||||
addChild(createWidget<Knurlie>(Vec(box.size.x - 30, 365))); | |||||
addParam(createParam<BefacoSwitch>(Vec(94, 32), module, Rampage::RANGE_A_PARAM)); | addParam(createParam<BefacoSwitch>(Vec(94, 32), module, Rampage::RANGE_A_PARAM)); | ||||
addParam(createParam<BefacoTinyKnob>(Vec(27, 90), module, Rampage::SHAPE_A_PARAM)); | addParam(createParam<BefacoTinyKnob>(Vec(27, 90), module, Rampage::SHAPE_A_PARAM)); | ||||
@@ -350,7 +357,7 @@ struct RampageWidget : ModuleWidget { | |||||
addInput(createInput<PJ301MPort>(Vec(67, 268), module, Rampage::FALL_CV_A_INPUT)); | addInput(createInput<PJ301MPort>(Vec(67, 268), module, Rampage::FALL_CV_A_INPUT)); | ||||
addInput(createInput<PJ301MPort>(Vec(38, 297), module, Rampage::EXP_CV_A_INPUT)); | addInput(createInput<PJ301MPort>(Vec(38, 297), module, Rampage::EXP_CV_A_INPUT)); | ||||
addInput(createInput<PJ301MPort>(Vec(102, 290), module, Rampage::CYCLE_A_INPUT)); | addInput(createInput<PJ301MPort>(Vec(102, 290), module, Rampage::CYCLE_A_INPUT)); | ||||
addInput(createInput<PJ301MPort>(Vec(229, 30), module, Rampage::IN_B_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(229, 30), module, Rampage::IN_B_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(192, 37), module, Rampage::TRIGG_B_INPUT)); | addInput(createInput<PJ301MPort>(Vec(192, 37), module, Rampage::TRIGG_B_INPUT)); | ||||
addInput(createInput<PJ301MPort>(Vec(176, 268), module, Rampage::RISE_CV_B_INPUT)); | addInput(createInput<PJ301MPort>(Vec(176, 268), module, Rampage::RISE_CV_B_INPUT)); | ||||
addInput(createInput<PJ301MPort>(Vec(237, 268), module, Rampage::FALL_CV_B_INPUT)); | addInput(createInput<PJ301MPort>(Vec(237, 268), module, Rampage::FALL_CV_B_INPUT)); | ||||
@@ -44,41 +44,40 @@ struct SlewLimiter : Module { | |||||
const float slewMin = 0.1; | const float slewMin = 0.1; | ||||
const float slewMax = 10000.f; | const float slewMax = 10000.f; | ||||
// Amount of extra slew per voltage difference | // Amount of extra slew per voltage difference | ||||
const float shapeScale = 1/10.f; | |||||
const float shapeScale = 1 / 10.f; | |||||
const simd::float_4 shape = simd::float_4(params[SHAPE_PARAM].getValue()); | const simd::float_4 shape = simd::float_4(params[SHAPE_PARAM].getValue()); | ||||
const simd::float_4 param_rise = simd::float_4(params[RISE_PARAM].getValue() * 10.f); | const simd::float_4 param_rise = simd::float_4(params[RISE_PARAM].getValue() * 10.f); | ||||
const simd::float_4 param_fall = simd::float_4(params[FALL_PARAM].getValue() * 10.f); | const simd::float_4 param_fall = simd::float_4(params[FALL_PARAM].getValue() * 10.f); | ||||
outputs[OUT_OUTPUT].setChannels(channels); | outputs[OUT_OUTPUT].setChannels(channels); | ||||
load_input(inputs[IN_INPUT], in, channels); | |||||
load_input(inputs[RISE_INPUT], riseCV, channels); | |||||
load_input(inputs[FALL_INPUT], fallCV, channels); | |||||
load_input(inputs[IN_INPUT], in, channels); | |||||
load_input(inputs[RISE_INPUT], riseCV, channels); | |||||
load_input(inputs[FALL_INPUT], fallCV, channels); | |||||
for(int c=0; c<channels; c+=4) { | |||||
riseCV[c/4] += param_rise; | |||||
fallCV[c/4] += param_fall; | |||||
for (int c = 0; c < channels; c += 4) { | |||||
riseCV[c / 4] += param_rise; | |||||
fallCV[c / 4] += param_fall; | |||||
simd::float_4 delta = in[c/4] - out[c/4]; | |||||
simd::float_4 delta = in[c / 4] - out[c / 4]; | |||||
simd::float_4 delta_gt_0 = delta > simd::float_4::zero(); | simd::float_4 delta_gt_0 = delta > simd::float_4::zero(); | ||||
simd::float_4 delta_lt_0 = delta < simd::float_4::zero(); | simd::float_4 delta_lt_0 = delta < simd::float_4::zero(); | ||||
simd::float_4 rateCV; | simd::float_4 rateCV; | ||||
rateCV = ifelse(delta_gt_0, riseCV[c/4], simd::float_4::zero()); | |||||
rateCV = ifelse(delta_lt_0, fallCV[c/4], rateCV) * 0.1f; | |||||
rateCV = ifelse(delta_gt_0, riseCV[c / 4], simd::float_4::zero()); | |||||
rateCV = ifelse(delta_lt_0, fallCV[c / 4], rateCV) * 0.1f; | |||||
simd::float_4 pm_one = simd::sgn(delta); | simd::float_4 pm_one = simd::sgn(delta); | ||||
simd::float_4 slew = slewMax * simd::pow(simd::float_4(slewMin / slewMax), rateCV); | simd::float_4 slew = slewMax * simd::pow(simd::float_4(slewMin / slewMax), rateCV); | ||||
out[c/4] += slew * simd::crossfade(pm_one, shapeScale*delta, shape) * args.sampleTime; | |||||
out[c/4] = ifelse( delta_gt_0 & (out[c/4]>in[c/4]), in[c/4], out[c/4]); | |||||
out[c/4] = ifelse( delta_lt_0 & (out[c/4]<in[c/4]), in[c/4], out[c/4]); | |||||
out[c / 4] += slew * simd::crossfade(pm_one, shapeScale * delta, shape) * args.sampleTime; | |||||
out[c / 4] = ifelse(delta_gt_0 & (out[c / 4] > in[c / 4]), in[c / 4], out[c / 4]); | |||||
out[c / 4] = ifelse(delta_lt_0 & (out[c / 4] < in[c / 4]), in[c / 4], out[c / 4]); | |||||
out[c/4].store(outputs[OUT_OUTPUT].getVoltages(c)); | |||||
out[c / 4].store(outputs[OUT_OUTPUT].getVoltages(c)); | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
@@ -32,15 +32,15 @@ struct SpringReverb : Module { | |||||
}; | }; | ||||
enum LightIds { | enum LightIds { | ||||
PEAK_LIGHT, | PEAK_LIGHT, | ||||
VU1_LIGHT, | |||||
NUM_LIGHTS = VU1_LIGHT + 7 | |||||
ENUMS(VU1_LIGHTS, 7), | |||||
NUM_LIGHTS | |||||
}; | }; | ||||
dsp::RealTimeConvolver *convolver = NULL; | dsp::RealTimeConvolver *convolver = NULL; | ||||
dsp::SampleRateConverter<1> inputSrc; | dsp::SampleRateConverter<1> inputSrc; | ||||
dsp::SampleRateConverter<1> outputSrc; | dsp::SampleRateConverter<1> outputSrc; | ||||
dsp::DoubleRingBuffer<dsp::Frame<1>, 16*BLOCK_SIZE> inputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<1>, 16*BLOCK_SIZE> outputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<1>, 16 * BLOCK_SIZE> inputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<1>, 16 * BLOCK_SIZE> outputBuffer; | |||||
dsp::RCFilter dryFilter; | dsp::RCFilter dryFilter; | ||||
dsp::PeakFilter vuFilter; | dsp::PeakFilter vuFilter; | ||||
@@ -55,7 +55,7 @@ struct SpringReverb : Module { | |||||
convolver = new dsp::RealTimeConvolver(BLOCK_SIZE); | convolver = new dsp::RealTimeConvolver(BLOCK_SIZE); | ||||
const float *kernel = (const float*) BINARY_START(src_SpringReverbIR_pcm); | |||||
const float *kernel = (const float *) BINARY_START(src_SpringReverbIR_pcm); | |||||
size_t kernelLen = BINARY_SIZE(src_SpringReverbIR_pcm) / sizeof(float); | size_t kernelLen = BINARY_SIZE(src_SpringReverbIR_pcm) / sizeof(float); | ||||
convolver->setKernel(kernel, kernelLen); | convolver->setKernel(kernel, kernelLen); | ||||
} | } | ||||
@@ -94,7 +94,7 @@ struct SpringReverb : Module { | |||||
inputSrc.setRates(args.sampleRate, 48000); | inputSrc.setRates(args.sampleRate, 48000); | ||||
int inLen = inputBuffer.size(); | int inLen = inputBuffer.size(); | ||||
int outLen = BLOCK_SIZE; | int outLen = BLOCK_SIZE; | ||||
inputSrc.process(inputBuffer.startData(), &inLen, (dsp::Frame<1>*) input, &outLen); | |||||
inputSrc.process(inputBuffer.startData(), &inLen, (dsp::Frame<1> *) input, &outLen); | |||||
inputBuffer.startIncr(inLen); | inputBuffer.startIncr(inLen); | ||||
} | } | ||||
@@ -106,7 +106,7 @@ struct SpringReverb : Module { | |||||
outputSrc.setRates(48000, args.sampleRate); | outputSrc.setRates(48000, args.sampleRate); | ||||
int inLen = BLOCK_SIZE; | int inLen = BLOCK_SIZE; | ||||
int outLen = outputBuffer.capacity(); | int outLen = outputBuffer.capacity(); | ||||
outputSrc.process((dsp::Frame<1>*) output, &inLen, outputBuffer.endData(), &outLen); | |||||
outputSrc.process((dsp::Frame<1> *) output, &inLen, outputBuffer.endData(), &outLen); | |||||
outputBuffer.endIncr(outLen); | outputBuffer.endIncr(outLen); | ||||
} | } | ||||
} | } | ||||
@@ -126,12 +126,12 @@ struct SpringReverb : Module { | |||||
vuFilter.setRate(lightRate); | vuFilter.setRate(lightRate); | ||||
vuFilter.process(std::fabs(wet)); | vuFilter.process(std::fabs(wet)); | ||||
lightFilter.setRate(lightRate); | lightFilter.setRate(lightRate); | ||||
lightFilter.process(std::fabs(dry*50.0)); | |||||
lightFilter.process(std::fabs(dry * 50.0)); | |||||
float vuValue = vuFilter.peak(); | float vuValue = vuFilter.peak(); | ||||
for (int i = 0; i < 7; i++) { | for (int i = 0; i < 7; i++) { | ||||
float light = std::pow(1.413, i) * vuValue / 10.0 - 1.0; | float light = std::pow(1.413, i) * vuValue / 10.0 - 1.0; | ||||
lights[VU1_LIGHT + i].value = clamp(light, 0.0f, 1.0f); | |||||
lights[VU1_LIGHTS + i].value = clamp(light, 0.0f, 1.0f); | |||||
} | } | ||||
lights[PEAK_LIGHT].value = lightFilter.peak(); | lights[PEAK_LIGHT].value = lightFilter.peak(); | ||||
} | } | ||||
@@ -145,8 +145,8 @@ struct SpringReverbWidget : ModuleWidget { | |||||
addChild(createWidget<Knurlie>(Vec(15, 0))); | addChild(createWidget<Knurlie>(Vec(15, 0))); | ||||
addChild(createWidget<Knurlie>(Vec(15, 365))); | addChild(createWidget<Knurlie>(Vec(15, 365))); | ||||
addChild(createWidget<Knurlie>(Vec(15*6, 0))); | |||||
addChild(createWidget<Knurlie>(Vec(15*6, 365))); | |||||
addChild(createWidget<Knurlie>(Vec(15 * 6, 0))); | |||||
addChild(createWidget<Knurlie>(Vec(15 * 6, 365))); | |||||
addParam(createParam<BefacoBigKnob>(Vec(22, 29), module, SpringReverb::WET_PARAM)); | addParam(createParam<BefacoBigKnob>(Vec(22, 29), module, SpringReverb::WET_PARAM)); | ||||
@@ -165,13 +165,13 @@ struct SpringReverbWidget : ModuleWidget { | |||||
addOutput(createOutput<PJ301MPort>(Vec(88, 317), module, SpringReverb::WET_OUTPUT)); | addOutput(createOutput<PJ301MPort>(Vec(88, 317), module, SpringReverb::WET_OUTPUT)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(55, 269), module, SpringReverb::PEAK_LIGHT)); | addChild(createLight<MediumLight<GreenRedLight>>(Vec(55, 269), module, SpringReverb::PEAK_LIGHT)); | ||||
addChild(createLight<MediumLight<RedLight>>(Vec(55, 113), module, SpringReverb::VU1_LIGHT + 0)); | |||||
addChild(createLight<MediumLight<YellowLight>>(Vec(55, 126), module, SpringReverb::VU1_LIGHT + 1)); | |||||
addChild(createLight<MediumLight<YellowLight>>(Vec(55, 138), module, SpringReverb::VU1_LIGHT + 2)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(55, 150), module, SpringReverb::VU1_LIGHT + 3)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(55, 163), module, SpringReverb::VU1_LIGHT + 4)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(55, 175), module, SpringReverb::VU1_LIGHT + 5)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(55, 188), module, SpringReverb::VU1_LIGHT + 6)); | |||||
addChild(createLight<MediumLight<RedLight>>(Vec(55, 113), module, SpringReverb::VU1_LIGHTS + 0)); | |||||
addChild(createLight<MediumLight<YellowLight>>(Vec(55, 126), module, SpringReverb::VU1_LIGHTS + 1)); | |||||
addChild(createLight<MediumLight<YellowLight>>(Vec(55, 138), module, SpringReverb::VU1_LIGHTS + 2)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(55, 150), module, SpringReverb::VU1_LIGHTS + 3)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(55, 163), module, SpringReverb::VU1_LIGHTS + 4)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(55, 175), module, SpringReverb::VU1_LIGHTS + 5)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(55, 188), module, SpringReverb::VU1_LIGHTS + 6)); | |||||
} | } | ||||
}; | }; | ||||
@@ -3,22 +3,26 @@ | |||||
#include "rack.hpp" | #include "rack.hpp" | ||||
inline void load_input(Input &in, simd::float_4 *v, int numChannels) { | inline void load_input(Input &in, simd::float_4 *v, int numChannels) { | ||||
int inChannels = in.getChannels(); | int inChannels = in.getChannels(); | ||||
if(inChannels==1) { | |||||
for(int i=0; i<numChannels; i++) v[i] = simd::float_4(in.getVoltage()); | |||||
} else { | |||||
for(int c=0; c<inChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c)); | |||||
if (inChannels == 1) { | |||||
for (int i = 0; i < numChannels; i++) | |||||
v[i] = simd::float_4(in.getVoltage()); | |||||
} | |||||
else { | |||||
for (int c = 0; c < inChannels; c += 4) | |||||
v[c / 4] = simd::float_4::load(in.getVoltages(c)); | |||||
} | } | ||||
} | } | ||||
inline void add_input(Input &in, simd::float_4 *v, int numChannels) { | inline void add_input(Input &in, simd::float_4 *v, int numChannels) { | ||||
int inChannels = in.getChannels(); | int inChannels = in.getChannels(); | ||||
if(inChannels==1) { | |||||
for(int i=0; i<numChannels; i++) v[i] += simd::float_4(in.getVoltage()); | |||||
} else { | |||||
for(int c=0; c<inChannels; c+=4) v[c/4] += simd::float_4::load(in.getVoltages(c)); | |||||
if (inChannels == 1) { | |||||
for (int i = 0; i < numChannels; i++) | |||||
v[i] += simd::float_4(in.getVoltage()); | |||||
} | |||||
else { | |||||
for (int c = 0; c < inChannels; c += 4) | |||||
v[c / 4] += simd::float_4::load(in.getVoltages(c)); | |||||
} | } | ||||
} | } | ||||