Signed-off-by: hemmer <915048+hemmer@users.noreply.github.com>tags/v1.1.0^2
@@ -13,7 +13,8 @@ | |||
"slug": "EvenVCO", | |||
"name": "EvenVCO", | |||
"tags": [ | |||
"VCO" | |||
"VCO", | |||
"Polyphonic" | |||
] | |||
}, | |||
{ | |||
@@ -3,7 +3,7 @@ | |||
#define MAX(a,b) (a>b)?a:b | |||
/* | |||
static float clip(float x) { | |||
// Pade approximant of x/(1 + x^12)^(1/12) | |||
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)) | |||
/ (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) { | |||
// Pade approximant of x/(1 + x^12)^(1/12) | |||
@@ -61,13 +62,11 @@ struct ABC : Module { | |||
NUM_OUTPUTS | |||
}; | |||
enum LightIds { | |||
ENUMS(OUT1_LIGHT, 2), | |||
ENUMS(OUT2_LIGHT, 2), | |||
ENUMS(OUT1_LIGHT, 3), | |||
ENUMS(OUT2_LIGHT, 3), | |||
NUM_LIGHTS | |||
}; | |||
// simd::float_4 mask[4]; | |||
ChannelMask channelMask; | |||
@@ -77,16 +76,6 @@ struct ABC : Module { | |||
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(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 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 | |||
@@ -184,8 +181,8 @@ struct ABC : Module { | |||
else { | |||
for(int c=0; c<channels_1; c+=4) out2[c/4] += out1[c/4]; | |||
channels_2 = MAX(channels_1, channels_2); | |||
} | |||
if (outputs[OUT2_OUTPUT].isConnected()) { | |||
outputs[OUT2_OUTPUT].setChannels(channels_2); | |||
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) { | |||
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 { | |||
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) { | |||
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 { | |||
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)); | |||
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 | |||
}; | |||
enum LightIds { | |||
OUT1_POS_LIGHT, | |||
OUT1_NEG_LIGHT, | |||
OUT2_POS_LIGHT, | |||
OUT2_NEG_LIGHT, | |||
ENUMS(OUT1_LIGHT, 3), | |||
ENUMS(OUT2_LIGHT, 3), | |||
NUM_LIGHTS | |||
}; | |||
@@ -62,10 +60,28 @@ struct DualAtenuverter : Module { | |||
float light1 = outputs[OUT1_OUTPUT].getVoltageSum()/channels1; | |||
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)); | |||
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; | |||
} | |||
/* | |||
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 { | |||
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. */ | |||
simd::float_4 process(float deltaTime) { | |||
inline simd::float_4 process(float deltaTime) { | |||
simd::float_4 mask = (remaining > simd::float_4::zero()); | |||
@@ -23,7 +23,7 @@ struct PulseGenerator_4 { | |||
} | |||
/** 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. | |||
simd::float_4 duration_4 = simd::float_4(duration); | |||
remaining = ifelse( mask&(duration_4>remaining), duration_4, remaining); | |||
@@ -64,15 +64,15 @@ struct Rampage : Module { | |||
NUM_OUTPUTS | |||
}; | |||
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 | |||
}; | |||
@@ -118,11 +118,11 @@ struct Rampage : Module { | |||
// determine number of channels: | |||
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(1, channels[part]); | |||
outputs[OUT_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]); | |||
outputs[COMPARATOR_OUTPUT].setChannels(channels_max); | |||
outputs[MIN_OUTPUT].setChannels(channels_max); | |||
outputs[MAX_OUTPUT].setChannels(channels_max); | |||
// loop over two parts of Rampage: | |||
for (int part = 0; part < 2; part++) { | |||
simd::float_4 in[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 minTime; | |||
@@ -150,11 +156,22 @@ struct Rampage : Module { | |||
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); | |||
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()) { | |||
load_input(inputs[IN_A_INPUT + part], 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()) { | |||
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]); | |||
} 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()) { | |||
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) { | |||
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]; | |||
// rise / fall branching | |||
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_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); | |||
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; | |||
@@ -249,14 +251,25 @@ struct Rampage : Module { | |||
} // for(int c, ...) | |||
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 { | |||
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 | |||
@@ -323,9 +336,9 @@ struct Rampage : Module { | |||
simd::float_4 b = out[1][c/4]; | |||
if (balance < 0.5) | |||
b *= 2.0 * balance; | |||
b *= 2.0f * balance; | |||
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 out_min = simd::fmin(a,b); | |||
@@ -337,9 +350,27 @@ struct Rampage : Module { | |||
} | |||
// 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() | |||
}; | |||
@@ -377,7 +408,7 @@ struct RampageWidget : ModuleWidget { | |||
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(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(176, 268), module, Rampage::RISE_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(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) { | |||
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 { | |||
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) { | |||
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 { | |||
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)); | |||
} | |||
} | |||