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)); | |||
| } | |||
| } | |||