Signed-off-by: hemmer <915048+hemmer@users.noreply.github.com>tags/v1.1.0^2
@@ -13,7 +13,8 @@ | |||||
"slug": "EvenVCO", | "slug": "EvenVCO", | ||||
"name": "EvenVCO", | "name": "EvenVCO", | ||||
"tags": [ | "tags": [ | ||||
"VCO" | |||||
"VCO", | |||||
"Polyphonic" | |||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
@@ -3,7 +3,7 @@ | |||||
#define MAX(a,b) (a>b)?a:b | #define MAX(a,b) (a>b)?a:b | ||||
/* | |||||
static float clip(float x) { | static float clip(float x) { | ||||
// Pade approximant of x/(1 + x^12)^(1/12) | // Pade approximant of x/(1 + x^12)^(1/12) | ||||
const float limit = 1.16691853009184; | const float limit = 1.16691853009184; | ||||
@@ -11,6 +11,7 @@ static float clip(float x) { | |||||
return (x + 1.45833*std::pow(x, 13) + 0.559028*std::pow(x, 25) + 0.0427035*std::pow(x, 37)) | return (x + 1.45833*std::pow(x, 13) + 0.559028*std::pow(x, 25) + 0.0427035*std::pow(x, 37)) | ||||
/ (1. + 1.54167*std::pow(x, 12) + 0.642361*std::pow(x, 24) + 0.0579909*std::pow(x, 36)); | / (1. + 1.54167*std::pow(x, 12) + 0.642361*std::pow(x, 24) + 0.0579909*std::pow(x, 36)); | ||||
} | } | ||||
*/ | |||||
static simd::float_4 clip4(simd::float_4 x) { | static simd::float_4 clip4(simd::float_4 x) { | ||||
// Pade approximant of x/(1 + x^12)^(1/12) | // Pade approximant of x/(1 + x^12)^(1/12) | ||||
@@ -61,13 +62,11 @@ struct ABC : Module { | |||||
NUM_OUTPUTS | NUM_OUTPUTS | ||||
}; | }; | ||||
enum LightIds { | enum LightIds { | ||||
ENUMS(OUT1_LIGHT, 2), | |||||
ENUMS(OUT2_LIGHT, 2), | |||||
ENUMS(OUT1_LIGHT, 3), | |||||
ENUMS(OUT2_LIGHT, 3), | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
// simd::float_4 mask[4]; | |||||
ChannelMask channelMask; | ChannelMask channelMask; | ||||
@@ -77,16 +76,6 @@ struct ABC : Module { | |||||
configParam(C1_LEVEL_PARAM, -1.0, 1.0, 0.0, "C1 Level"); | configParam(C1_LEVEL_PARAM, -1.0, 1.0, 0.0, "C1 Level"); | ||||
configParam(B2_LEVEL_PARAM, -1.0, 1.0, 0.0, "B2 Level"); | configParam(B2_LEVEL_PARAM, -1.0, 1.0, 0.0, "B2 Level"); | ||||
configParam(C2_LEVEL_PARAM, -1.0, 1.0, 0.0, "C2 Level"); | configParam(C2_LEVEL_PARAM, -1.0, 1.0, 0.0, "C2 Level"); | ||||
/* | |||||
__m128i tmp = _mm_cmpeq_epi16(_mm_set_epi32(0,0,0,0),_mm_set_epi32(0,0,0,0)); | |||||
for(int i=0; i<4; i++) { | |||||
mask[3-i] = simd::float_4(_mm_castsi128_ps(tmp)); | |||||
tmp = _mm_srli_si128(tmp, 4); | |||||
} | |||||
*/ | |||||
} | } | ||||
@@ -104,76 +93,84 @@ struct ABC : Module { | |||||
simd::float_4 c2[4]; | simd::float_4 c2[4]; | ||||
simd::float_4 out2[4]; | simd::float_4 out2[4]; | ||||
int channels_A1 = inputs[A1_INPUT].getChannels(); | |||||
int channels_A2 = inputs[A2_INPUT].getChannels(); | |||||
int channels_1 = 1; | |||||
int channels_2 = 1; | |||||
int channels_B1 = inputs[B1_INPUT].getChannels(); | |||||
int channels_B2 = inputs[B2_INPUT].getChannels(); | |||||
int channels_C1 = inputs[C1_INPUT].getChannels(); | |||||
int channels_C2 = inputs[C2_INPUT].getChannels(); | |||||
int channels_1 = 1; | |||||
channels_1 = MAX(channels_1, channels_A1); | |||||
channels_1 = MAX(channels_1, channels_B1); | |||||
channels_1 = MAX(channels_1, channels_C1); | |||||
// process upper section | |||||
int channels_2 = 1; | |||||
channels_2 = MAX(channels_2, channels_A2); | |||||
channels_2 = MAX(channels_2, channels_B2); | |||||
channels_2 = MAX(channels_2, channels_C2); | |||||
if(outputs[OUT1_OUTPUT].isConnected() || outputs[OUT2_OUTPUT].isConnected() ) { | |||||
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()); | |||||
int channels_A1 = inputs[A1_INPUT].getChannels(); | |||||
int channels_B1 = inputs[B1_INPUT].getChannels(); | |||||
int channels_C1 = inputs[C1_INPUT].getChannels(); | |||||
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()); | |||||
channels_1 = MAX(channels_1, channels_A1); | |||||
channels_1 = MAX(channels_1, channels_B1); | |||||
channels_1 = MAX(channels_1, channels_C1); | |||||
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()); | |||||
load_input(inputs[A1_INPUT], a1, channels_A1); | |||||
channelMask.apply(a1, channels_1); | |||||
load_input(inputs[A1_INPUT], a1, channels_A1); | |||||
channelMask.apply(a1, channels_1); | |||||
if(inputs[B1_INPUT].isConnected()) { | |||||
load_input(inputs[B1_INPUT], b1, channels_B1); | |||||
for(int c=0; c<channels_1; c+=4) b1[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); | |||||
} | |||||
channelMask.apply(b1, channels_1); | |||||
if(inputs[B1_INPUT].isConnected()) { | |||||
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); | |||||
} | |||||
channelMask.apply(b1, channels_1); | |||||
if(inputs[C1_INPUT].isConnected()) { | |||||
load_input(inputs[C1_INPUT], c1, channels_C1); | |||||
for(int c=0; c<channels_1; c+=4) c1[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); | |||||
if(inputs[C1_INPUT].isConnected()) { | |||||
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); | |||||
} | |||||
channelMask.apply(c1, channels_1); | |||||
for(int c=0; c<channels_1; c+=4) out1[c/4] = clip4(a1[c/4] * b1[c/4] + c1[c/4]); | |||||
} | } | ||||
channelMask.apply(c1, channels_1); | |||||
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 | |||||
if(outputs[OUT2_OUTPUT].isConnected()) { | |||||
int channels_A2 = inputs[A2_INPUT].getChannels(); | |||||
int channels_B2 = inputs[B2_INPUT].getChannels(); | |||||
int channels_C2 = inputs[C2_INPUT].getChannels(); | |||||
load_input(inputs[A2_INPUT], a2, channels_A2); | |||||
channelMask.apply(a2, channels_2); | |||||
channels_2 = MAX(channels_2, channels_A2); | |||||
channels_2 = MAX(channels_2, channels_B2); | |||||
channels_2 = MAX(channels_2, channels_C2); | |||||
if(inputs[B2_INPUT].isConnected()) { | |||||
load_input(inputs[B2_INPUT], b2, channels_B2); | |||||
for(int c=0; c<channels_2; c+=4) b2[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); | |||||
} | |||||
channelMask.apply(b2, channels_2); | |||||
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()); | |||||
if(inputs[C2_INPUT].isConnected()) { | |||||
load_input(inputs[C2_INPUT], c2, channels_C2); | |||||
for(int c=0; c<channels_2; c+=4) c2[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); | |||||
} | |||||
channelMask.apply(c2, channels_2); | |||||
load_input(inputs[A2_INPUT], a2, channels_A2); | |||||
channelMask.apply(a2, channels_2); | |||||
if(inputs[B2_INPUT].isConnected()) { | |||||
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); | |||||
} | |||||
channelMask.apply(b2, channels_2); | |||||
for(int c=0; c<channels_2; c+=4) out2[c/4] = clip4(a2[c/4] * b2[c/4] + c2[c/4]); | |||||
if(inputs[C2_INPUT].isConnected()) { | |||||
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); | |||||
} | |||||
channelMask.apply(c2, channels_2); | |||||
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 | ||||
@@ -184,8 +181,8 @@ struct ABC : Module { | |||||
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 = MAX(channels_1, channels_2); | channels_2 = 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)); | ||||
@@ -198,19 +195,28 @@ struct ABC : Module { | |||||
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 + 1].setSmoothBrightness(-light_1 / 5.f, args.sampleTime); | |||||
lights[OUT1_LIGHT + 2].setBrightness(0.f); | |||||
} else { | } else { | ||||
light_1 = outputs[OUT1_OUTPUT].getVoltageSum(); | |||||
light_1 = 10.f; | |||||
lights[OUT1_LIGHT + 0].setBrightness(0.0f); | |||||
lights[OUT1_LIGHT + 1].setBrightness(0.0f); | |||||
lights[OUT1_LIGHT + 2].setBrightness(light_1); | |||||
} | } | ||||
lights[OUT1_LIGHT + 0].setSmoothBrightness(light_1 / 5.f, args.sampleTime); | |||||
lights[OUT1_LIGHT + 1].setSmoothBrightness(-light_1 / 5.f, args.sampleTime); | |||||
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 + 1].setSmoothBrightness(-light_2 / 5.f, args.sampleTime); | |||||
lights[OUT2_LIGHT + 2].setBrightness(0.f); | |||||
} else { | } else { | ||||
light_2 = outputs[OUT2_OUTPUT].getVoltageSum(); | |||||
light_2 = 10.f; | |||||
lights[OUT2_LIGHT + 0].setBrightness(0.0f); | |||||
lights[OUT2_LIGHT + 1].setBrightness(0.0f); | |||||
lights[OUT2_LIGHT + 2].setBrightness(light_2); | |||||
} | } | ||||
lights[OUT2_LIGHT + 0].setSmoothBrightness(light_2 / 5.f, args.sampleTime); | |||||
lights[OUT2_LIGHT + 1].setSmoothBrightness(-light_2 / 5.f, args.sampleTime); | |||||
} | } | ||||
}; | }; | ||||
@@ -238,8 +244,8 @@ struct ABCWidget : ModuleWidget { | |||||
addInput(createInput<PJ301MPort>(Vec(7, 279), module, ABC::C2_INPUT)); | addInput(createInput<PJ301MPort>(Vec(7, 279), module, ABC::C2_INPUT)); | ||||
addOutput(createOutput<PJ301MPort>(Vec(7, 321), module, ABC::OUT2_OUTPUT)); | addOutput(createOutput<PJ301MPort>(Vec(7, 321), module, ABC::OUT2_OUTPUT)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(37, 162), module, ABC::OUT1_LIGHT)); | |||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(37, 329), module, ABC::OUT2_LIGHT)); | |||||
addChild(createLight<MediumLight<RedGreenBlueLight>>(Vec(37, 162), module, ABC::OUT1_LIGHT)); | |||||
addChild(createLight<MediumLight<RedGreenBlueLight>>(Vec(37, 329), module, ABC::OUT2_LIGHT)); | |||||
} | } | ||||
}; | }; | ||||
@@ -21,10 +21,8 @@ struct DualAtenuverter : Module { | |||||
NUM_OUTPUTS | NUM_OUTPUTS | ||||
}; | }; | ||||
enum LightIds { | enum LightIds { | ||||
OUT1_POS_LIGHT, | |||||
OUT1_NEG_LIGHT, | |||||
OUT2_POS_LIGHT, | |||||
OUT2_NEG_LIGHT, | |||||
ENUMS(OUT1_LIGHT, 3), | |||||
ENUMS(OUT2_LIGHT, 3), | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
@@ -62,10 +60,28 @@ struct DualAtenuverter : Module { | |||||
float light1 = outputs[OUT1_OUTPUT].getVoltageSum()/channels1; | float light1 = outputs[OUT1_OUTPUT].getVoltageSum()/channels1; | ||||
float light2 = outputs[OUT2_OUTPUT].getVoltageSum()/channels2; | float light2 = outputs[OUT2_OUTPUT].getVoltageSum()/channels2; | ||||
lights[OUT1_POS_LIGHT].setSmoothBrightness(light1 / 5.f, args.sampleTime); | |||||
lights[OUT1_NEG_LIGHT].setSmoothBrightness(-light1 / 5.f, args.sampleTime); | |||||
lights[OUT2_POS_LIGHT].setSmoothBrightness(light2 / 5.f, args.sampleTime); | |||||
lights[OUT2_NEG_LIGHT].setSmoothBrightness(-light2 / 5.f, args.sampleTime); | |||||
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); | |||||
} | |||||
} | } | ||||
}; | }; | ||||
@@ -89,8 +105,8 @@ struct DualAtenuverterWidget : ModuleWidget { | |||||
addInput(createInput<PJ301MPort>(Vec(7, 319), module, DualAtenuverter::IN2_INPUT)); | addInput(createInput<PJ301MPort>(Vec(7, 319), module, DualAtenuverter::IN2_INPUT)); | ||||
addOutput(createOutput<PJ301MPort>(Vec(43, 319), module, DualAtenuverter::OUT2_OUTPUT)); | addOutput(createOutput<PJ301MPort>(Vec(43, 319), module, DualAtenuverter::OUT2_OUTPUT)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(33, 143), module, DualAtenuverter::OUT1_POS_LIGHT)); | |||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(33, 311), module, DualAtenuverter::OUT2_POS_LIGHT)); | |||||
addChild(createLight<MediumLight<RedGreenBlueLight>>(Vec(33, 143), module, DualAtenuverter::OUT1_LIGHT)); | |||||
addChild(createLight<MediumLight<RedGreenBlueLight>>(Vec(33, 311), module, DualAtenuverter::OUT2_LIGHT)); | |||||
} | } | ||||
}; | }; | ||||
@@ -60,24 +60,6 @@ struct EvenVCO : Module { | |||||
for(int c=0; c<PORT_MAX_CHANNELS; c++) halfPhase[c] = false; | for(int c=0; c<PORT_MAX_CHANNELS; c++) halfPhase[c] = false; | ||||
} | } | ||||
/* | |||||
inline void load_input(Input &in, simd::float_4 *v, int numChannels) { | |||||
if(numChannels==1) { | |||||
for(int i=0; i<4; i++) v[i] = simd::float_4(in.getVoltage()); | |||||
} else { | |||||
for(int c=0; c<numChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c)); | |||||
} | |||||
} | |||||
*/ | |||||
inline void add_input(Input &in, simd::float_4 *v, int numChannels) { | |||||
if(numChannels==1) { | |||||
for(int i=0; i<4; i++) v[i] = simd::float_4(in.getVoltage()); | |||||
} else { | |||||
for(int c=0; c<numChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c)); | |||||
} | |||||
} | |||||
void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
simd::float_4 pitch[4]; | simd::float_4 pitch[4]; | ||||
@@ -14,7 +14,7 @@ struct PulseGenerator_4 { | |||||
} | } | ||||
/** Advances the state by `deltaTime`. Returns whether the pulse is in the HIGH state. */ | /** Advances the state by `deltaTime`. Returns whether the pulse is in the HIGH state. */ | ||||
simd::float_4 process(float deltaTime) { | |||||
inline simd::float_4 process(float deltaTime) { | |||||
simd::float_4 mask = (remaining > simd::float_4::zero()); | simd::float_4 mask = (remaining > simd::float_4::zero()); | ||||
@@ -23,7 +23,7 @@ struct PulseGenerator_4 { | |||||
} | } | ||||
/** Begins a trigger with the given `duration`. */ | /** Begins a trigger with the given `duration`. */ | ||||
void trigger(simd::float_4 mask, float duration = 1e-3f) { | |||||
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. | // 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); | simd::float_4 duration_4 = simd::float_4(duration); | ||||
remaining = ifelse( mask&(duration_4>remaining), duration_4, remaining); | remaining = ifelse( mask&(duration_4>remaining), duration_4, remaining); | ||||
@@ -64,15 +64,15 @@ struct Rampage : Module { | |||||
NUM_OUTPUTS | NUM_OUTPUTS | ||||
}; | }; | ||||
enum LightIds { | enum LightIds { | ||||
COMPARATOR_LIGHT, | |||||
MIN_LIGHT, | |||||
MAX_LIGHT, | |||||
OUT_A_LIGHT, | |||||
OUT_B_LIGHT, | |||||
RISING_A_LIGHT, | |||||
RISING_B_LIGHT, | |||||
FALLING_A_LIGHT, | |||||
FALLING_B_LIGHT, | |||||
ENUMS(COMPARATOR_LIGHT, 3), | |||||
ENUMS(MIN_LIGHT, 3), | |||||
ENUMS(MAX_LIGHT, 3), | |||||
ENUMS(OUT_A_LIGHT, 3), | |||||
ENUMS(OUT_B_LIGHT, 3), | |||||
ENUMS(RISING_A_LIGHT, 3), | |||||
ENUMS(RISING_B_LIGHT, 3), | |||||
ENUMS(FALLING_A_LIGHT, 3), | |||||
ENUMS(FALLING_B_LIGHT, 3), | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
@@ -118,11 +118,11 @@ struct Rampage : Module { | |||||
// determine number of channels: | // determine number of channels: | ||||
for (int part=0; part<2; part++) { | for (int part=0; part<2; part++) { | ||||
int tmp = inputs[IN_A_INPUT+part].getChannels(); | |||||
channels_in[part] = MAX(1,tmp); | |||||
tmp = inputs[TRIGG_A_INPUT+part].getChannels(); | |||||
channels_trig[part] = MAX(1,tmp); | |||||
channels_in[part] = inputs[IN_A_INPUT+part].getChannels(); | |||||
channels_trig[part] = inputs[TRIGG_A_INPUT+part].getChannels(); | |||||
channels[part] = MAX(channels_in[part], channels_trig[part]); | channels[part] = MAX(channels_in[part], channels_trig[part]); | ||||
channels[part] = MAX(1, channels[part]); | |||||
outputs[OUT_A_OUTPUT+part].setChannels(channels[part]); | outputs[OUT_A_OUTPUT+part].setChannels(channels[part]); | ||||
outputs[RISING_A_OUTPUT+part].setChannels(channels[part]); | outputs[RISING_A_OUTPUT+part].setChannels(channels[part]); | ||||
@@ -131,16 +131,22 @@ struct Rampage : Module { | |||||
} | } | ||||
int channels_max = MAX(channels[0], channels[1]); | int channels_max = MAX(channels[0], channels[1]); | ||||
outputs[COMPARATOR_OUTPUT].setChannels(channels_max); | |||||
outputs[MIN_OUTPUT].setChannels(channels_max); | |||||
outputs[MAX_OUTPUT].setChannels(channels_max); | |||||
// loop over two parts of Rampage: | // loop over two parts of Rampage: | ||||
for (int part = 0; part < 2; part++) { | for (int part = 0; part < 2; part++) { | ||||
simd::float_4 in[4]; | simd::float_4 in[4]; | ||||
simd::float_4 in_trig[4]; | simd::float_4 in_trig[4]; | ||||
simd::float_4 expCV[4] = {}; | |||||
simd::float_4 riseCV[4] = {}; | |||||
simd::float_4 fallCV[4] = {}; | |||||
simd::float_4 cycle[4] = {}; | |||||
simd::float_4 expCV[4]; | |||||
simd::float_4 riseCV[4]; | |||||
simd::float_4 fallCV[4]; | |||||
simd::float_4 cycle[4]; | |||||
// get parameters: | |||||
float shape = params[SHAPE_A_PARAM + part].getValue(); | float shape = params[SHAPE_A_PARAM + part].getValue(); | ||||
float minTime; | float minTime; | ||||
@@ -150,11 +156,22 @@ struct Rampage : Module { | |||||
default: minTime = 1e-1; break; | default: minTime = 1e-1; break; | ||||
} | } | ||||
simd::float_4 param_rise = simd::float_4(params[RISE_A_PARAM + part].getValue()); | |||||
simd::float_4 param_fall = simd::float_4(params[FALL_A_PARAM + part].getValue()); | |||||
simd::float_4 param_trig = simd::float_4(params[TRIGG_A_PARAM + part].getValue() * 10.0f); | |||||
simd::float_4 param_rise = simd::float_4(params[RISE_A_PARAM + part].getValue() * 10.0f); | |||||
simd::float_4 param_fall = simd::float_4(params[FALL_A_PARAM + part].getValue() * 10.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; | |||||
} | |||||
// 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]); | ||||
@@ -163,61 +180,46 @@ struct Rampage : Module { | |||||
} | } | ||||
if(inputs[TRIGG_A_INPUT + part].isConnected()) { | if(inputs[TRIGG_A_INPUT + part].isConnected()) { | ||||
load_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]); | ||||
} else { | |||||
memset(in_trig, 0, sizeof(in_trig)); | |||||
} | |||||
for(int c=0; c<channels_trig[part]; c+=4) in_trig[c/4] = param_trig + in_trig[c/4]/2.0f; | |||||
channelMask.apply_all(in_trig, channels_trig[part] ); | |||||
for(int c=0; c<channels[part]; c+=4) { | |||||
simd::float_4 trig_mask = trigger_4[part][c/4].process(in_trig[c/4]); | |||||
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]); | |||||
} | |||||
} | |||||
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] *= -1.0f; | |||||
for(int c=0; c<channels[part]; c+=4) { | |||||
riseCV[c/4] -= expCV[c/4]; | |||||
fallCV[c/4] -= expCV[c/4]; | |||||
} | |||||
} | } | ||||
load_input(inputs[RISE_CV_A_INPUT + part], riseCV, channels[part]); | |||||
for(int c=0; c<channels[part]; c+=4) { | |||||
riseCV[c/4] += expCV[c/4]; | |||||
riseCV[c/4] *= 0.10f; | |||||
riseCV[c/4] += param_rise; | |||||
} | |||||
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]); | |||||
channelMask.apply(cycle, channels[part]); // check whether this is necessary | |||||
load_input(inputs[FALL_CV_A_INPUT + part], fallCV, channels[part]); | |||||
// start processing: | |||||
for(int c=0; c<channels[part]; c+=4) { | for(int c=0; c<channels[part]; c+=4) { | ||||
fallCV[c/4] += expCV[c/4]; | |||||
fallCV[c/4] *= 0.10f; | |||||
fallCV[c/4] += param_fall; | |||||
} | |||||
load_input(inputs[CYCLE_A_INPUT], cycle, channels[part]); | |||||
// channelMask.apply_all(cycle, channels[part]); | |||||
for(int c=0; c<channels[part]; c+=4) { | |||||
cycle[c/4] += param_cycle; | |||||
} | |||||
channelMask.apply_all(cycle, channels[part]); | |||||
// process SchmittTriggers | |||||
for(int c=0; c<channels[part]; 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 | |||||
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()); | 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 = ifelse(delta_lt_0, fallCV[c/4], rateCV); | ||||
rateCV = clamp(rateCV, simd::float_4::zero(), simd::float_4(1.0f)); | |||||
rateCV = clamp(rateCV, simd::float_4::zero(), simd::float_4(10.0f)); | |||||
simd::float_4 rate = minTime * simd::pow(2.0f, rateCV * 10.0f); | |||||
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; | ||||
@@ -249,14 +251,25 @@ struct Rampage : Module { | |||||
} // for(int c, ...) | } // for(int c, ...) | ||||
if(channels[part] == 1) { | if(channels[part] == 1) { | ||||
lights[RISING_A_LIGHT + part].setSmoothBrightness(outputs[RISING_A_OUTPUT+part].getVoltage()/10.f, args.sampleTime); | |||||
lights[FALLING_A_LIGHT + part].setSmoothBrightness(outputs[FALLING_A_OUTPUT+part].getVoltage()/10.f, args.sampleTime); | |||||
lights[OUT_A_LIGHT + part].setSmoothBrightness(out[part][0].s[0] / 10.0, args.sampleTime); | |||||
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 { | } else { | ||||
lights[RISING_A_LIGHT + part].setSmoothBrightness(outputs[RISING_A_OUTPUT+part].getVoltageSum()/10.f, args.sampleTime); | |||||
lights[FALLING_A_LIGHT + part].setSmoothBrightness(outputs[FALLING_A_OUTPUT+part].getVoltageSum()/10.f, args.sampleTime); | |||||
lights[OUT_A_LIGHT + part].setSmoothBrightness(outputs[OUT_A_OUTPUT].getVoltageSum() / 10.0, args.sampleTime); | |||||
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); | |||||
} | } | ||||
// Integrator | // Integrator | ||||
@@ -323,9 +336,9 @@ struct Rampage : Module { | |||||
simd::float_4 b = out[1][c/4]; | simd::float_4 b = out[1][c/4]; | ||||
if (balance < 0.5) | if (balance < 0.5) | ||||
b *= 2.0 * balance; | |||||
b *= 2.0f * balance; | |||||
else if (balance > 0.5) | else if (balance > 0.5) | ||||
a *= 2.0 * (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 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_min = simd::fmin(a,b); | ||||
@@ -337,9 +350,27 @@ struct Rampage : Module { | |||||
} | } | ||||
// Lights | // Lights | ||||
lights[COMPARATOR_LIGHT].setSmoothBrightness(outputs[COMPARATOR_OUTPUT].getVoltageSum() / 10.0, args.sampleTime); | |||||
lights[MIN_LIGHT].setSmoothBrightness(outputs[MIN_OUTPUT].getVoltageSum() / 10.0, args.sampleTime); | |||||
lights[MAX_LIGHT].setSmoothBrightness(outputs[MAX_OUTPUT].getVoltageSum() / 10.0, args.sampleTime); | |||||
if(channels_max==1) { | |||||
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[MIN_LIGHT ].setSmoothBrightness(outputs[MIN_OUTPUT].getVoltage(), args.sampleTime); | |||||
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+1].setBrightness(0.0f); | |||||
lights[MAX_LIGHT+2].setBrightness(0.0f); | |||||
} else { | |||||
lights[COMPARATOR_LIGHT ].setBrightness(0.0f); | |||||
lights[COMPARATOR_LIGHT+1].setBrightness(0.0f); | |||||
lights[COMPARATOR_LIGHT+2].setBrightness(10.0f); | |||||
lights[MIN_LIGHT ].setBrightness(0.0f); | |||||
lights[MIN_LIGHT+1].setBrightness(0.0f); | |||||
lights[MIN_LIGHT+2].setBrightness(10.0f); | |||||
lights[MAX_LIGHT ].setBrightness(0.0f); | |||||
lights[MAX_LIGHT+1].setBrightness(0.0f); | |||||
lights[MAX_LIGHT+2].setBrightness(10.0f); | |||||
} | |||||
} // end process() | } // end process() | ||||
}; | }; | ||||
@@ -377,7 +408,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)); | ||||
@@ -396,15 +427,15 @@ struct RampageWidget : ModuleWidget { | |||||
addOutput(createOutput<PJ301MPort>(Vec(89, 157), module, Rampage::MIN_OUTPUT)); | addOutput(createOutput<PJ301MPort>(Vec(89, 157), module, Rampage::MIN_OUTPUT)); | ||||
addOutput(createOutput<PJ301MPort>(Vec(155, 157), module, Rampage::MAX_OUTPUT)); | addOutput(createOutput<PJ301MPort>(Vec(155, 157), module, Rampage::MAX_OUTPUT)); | ||||
addChild(createLight<SmallLight<RedLight>>(Vec(132, 167), module, Rampage::COMPARATOR_LIGHT)); | |||||
addChild(createLight<SmallLight<RedLight>>(Vec(123, 174), module, Rampage::MIN_LIGHT)); | |||||
addChild(createLight<SmallLight<RedLight>>(Vec(141, 174), module, Rampage::MAX_LIGHT)); | |||||
addChild(createLight<SmallLight<RedLight>>(Vec(126, 185), module, Rampage::OUT_A_LIGHT)); | |||||
addChild(createLight<SmallLight<RedLight>>(Vec(138, 185), module, Rampage::OUT_B_LIGHT)); | |||||
addChild(createLight<SmallLight<RedLight>>(Vec(18, 312), module, Rampage::RISING_A_LIGHT)); | |||||
addChild(createLight<SmallLight<RedLight>>(Vec(78, 312), module, Rampage::FALLING_A_LIGHT)); | |||||
addChild(createLight<SmallLight<RedLight>>(Vec(187, 312), module, Rampage::RISING_B_LIGHT)); | |||||
addChild(createLight<SmallLight<RedLight>>(Vec(247, 312), module, Rampage::FALLING_B_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(132, 167), module, Rampage::COMPARATOR_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(123, 174), module, Rampage::MIN_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(141, 174), module, Rampage::MAX_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(126, 185), module, Rampage::OUT_A_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(138, 185), module, Rampage::OUT_B_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(18, 312), module, Rampage::RISING_A_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(78, 312), module, Rampage::FALLING_A_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(187, 312), module, Rampage::RISING_B_LIGHT)); | |||||
addChild(createLight<SmallLight<RedGreenBlueLight>>(Vec(247, 312), module, Rampage::FALLING_B_LIGHT)); | |||||
} | } | ||||
}; | }; | ||||
@@ -37,18 +37,20 @@ struct ChannelMask { | |||||
}; | }; | ||||
inline void load_input(Input &in, simd::float_4 *v, int numChannels) { | inline void load_input(Input &in, simd::float_4 *v, int numChannels) { | ||||
if(numChannels==1) { | |||||
for(int i=0; i<4; i++) v[i] = simd::float_4(in.getVoltage()); | |||||
int inChannels = in.getChannels(); | |||||
if(inChannels==1) { | |||||
for(int i=0; i<numChannels; i++) v[i] = simd::float_4(in.getVoltage()); | |||||
} else { | } else { | ||||
for(int c=0; c<numChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c)); | |||||
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) { | ||||
if(numChannels==1) { | |||||
for(int i=0; i<4; i++) v[i] += simd::float_4(in.getVoltage()); | |||||
int inChannels = in.getChannels(); | |||||
if(inChannels==1) { | |||||
for(int i=0; i<numChannels; i++) v[i] += simd::float_4(in.getVoltage()); | |||||
} else { | } else { | ||||
for(int c=0; c<numChannels; c+=4) v[c/4] += simd::float_4::load(in.getVoltages(c)); | |||||
for(int c=0; c<inChannels; c+=4) v[c/4] += simd::float_4::load(in.getVoltages(c)); | |||||
} | } | ||||
} | } | ||||