#include "common.hpp" #include "uncert.hpp" namespace rack_plugin_TheXOR { void Uncertain::on_loaded() { load(); } void Uncertain::load() { fluctParams.reset(); } void Uncertain::step() { if(inputs[CLOCK_FLUCT].active) out_fluct(clock_fluct.process(inputs[CLOCK_FLUCT].value)); else fluctParams.reset(); if(inputs[CLOCK_QUANTIZED].active) out_quantized(clock_quantized.process(inputs[CLOCK_QUANTIZED].value)); if(inputs[CLOCK_STORED].active) out_stored(clock_stored.process(inputs[CLOCK_STORED].value)); } void Uncertain::out_quantized(int clk) { if(clk == 1) { int position = getInt(QUANTIZED_AMT, IN_QUANTIZED, 0.0, 5.0)+1; outputs[OUT_QUANTIZED_N1].value = roundf(rescale(randomUniform(), 0.0, 1.0, 0.0, position)); // 1V float n2= roundf(rescale(randomUniform(), 0.0, 1.0, 1.0, 2 << position)); outputs[OUT_QUANTIZED_2N].value = clamp(Uncertain::SEMITONE*n2, 0.0, 10.0); } } void Uncertain::out_stored(int clk) { if(clk == 1) { outputs[OUT_STORED_RND].value = clamp(roundf(rescale(randomUniform(), 0.0, 1.0, 0.0, 1000.0)) * MIN_VOLTAGE, 0.0,10.0); outputs[OUT_STORED_BELL].value = rndGaussianVoltage(); } } float Uncertain::rndGaussianVoltage() { float mu = getFloat(STORED_AMT, IN_STORED, MIN_VOLTAGE, MAX_VOLTAGE); float sigma = getFloat(CURVEAMP_AMT, IN_CURVEAMP, 0.01, 2.0); float u1 = 1.0 - randomUniform(); float u2 = 1.0 - randomUniform(); float randStdNormal = sqrtf(-2.0 * logf(u1)) * sinf(2.0 * M_PI * u2); //random normal(0,1) return clamp(mu + sigma * randStdNormal, MIN_VOLTAGE, MAX_VOLTAGE); } float Uncertain::rndFluctVoltage() { float vmax = getFloat(FLUCT_AMT, IN_FLUCT, MIN_VOLTAGE, MAX_VOLTAGE); return clamp(rescale(randomUniform(), 0.0, 1.0, MIN_VOLTAGE, vmax), MIN_VOLTAGE, MAX_VOLTAGE); } void Uncertain::out_fluct(int clk) { switch(clk) { case 1: //rise { if(fluctParams.duration == 0) // 0 if first cycle { outputs[OUT_FLUCT].value = fluctParams.vA = fluctParams.vB = rndFluctVoltage(); } fluctParams.tStart = clock(); } break; case -1: //fall { fluctParams.vB = rndFluctVoltage(); fluctParams.duration = clock() - fluctParams.tStart; fluctParams.tStart = 0; if(fluctParams.duration > 0) { fluctParams.vA = outputs[OUT_FLUCT].value; fluctParams.deltaV = (fluctParams.vB - fluctParams.vA) / fluctParams.duration; } } break; default: // in progress { if(fluctParams.duration != 0 && fluctParams.tStart != 0) // 0 if first cycle { clock_t elapsed = clock() - fluctParams.tStart; float v = fluctParams.vA + fluctParams.deltaV * elapsed; outputs[OUT_FLUCT].value = clamp(v, MIN_VOLTAGE, MAX_VOLTAGE); } } break; } } float Uncertain::getFloat(ParamIds p_id, InputIds i_id, float minValue, float maxValue) { float offs = inputs[i_id].active ? rescale(inputs[i_id].value, 0.0, 5.0, minValue, maxValue) : 0.0; return clamp(offs + params[p_id].value, minValue, maxValue); } UncertainWidget::UncertainWidget(Uncertain *module) : SequencerWidget(module) { box.size = Vec(12 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT); { SVGPanel *panel = new SVGPanel(); panel->box.size = box.size; panel->setBackground(SVG::load(assetPlugin(plugin, "res/modules/uncert.svg"))); addChild(panel); } addChild(Widget::create(Vec(RACK_GRID_WIDTH, 0))); addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); addChild(Widget::create(Vec(RACK_GRID_WIDTH, box.size.y - RACK_GRID_WIDTH))); addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, box.size.y - RACK_GRID_WIDTH))); float lft_x = mm2px(4.726); float rgt_x = mm2px(47.988); float center_x = mm2px(25.717); addInput(Port::create(Vec(lft_x, yncscape(107.334,8.255)), Port::INPUT, module, Uncertain::CLOCK_FLUCT)); addInput(Port::create(Vec(lft_x, yncscape(89.809, 8.255)), Port::INPUT, module, Uncertain::IN_FLUCT)); addParam(ParamWidget::create(Vec(center_x, yncscape(97.936, 9.525)), module, Uncertain::FLUCT_AMT, Uncertain::MIN_VOLTAGE, Uncertain::MAX_VOLTAGE, Uncertain::MIN_VOLTAGE)); addOutput(Port::create(Vec(rgt_x, yncscape(98.571, 8.255)), Port::OUTPUT, module, Uncertain::OUT_FLUCT)); addInput(Port::create(Vec(lft_x, yncscape(68.885, 8.255)), Port::INPUT, module, Uncertain::CLOCK_QUANTIZED)); addInput(Port::create(Vec(lft_x, yncscape(51.360, 8.255)), Port::INPUT, module, Uncertain::IN_QUANTIZED)); ParamWidget *pw = ParamWidget::create(Vec(center_x, yncscape(59.487, 9.525)), module, Uncertain::QUANTIZED_AMT, 0.0, 5.0, 0.0); ((Davies1900hKnob *)pw)->snap = true; addParam(pw); addOutput(Port::create(Vec(rgt_x, yncscape(68.885, 8.255)), Port::OUTPUT, module, Uncertain::OUT_QUANTIZED_N1)); addOutput(Port::create(Vec(rgt_x, yncscape(51.360, 8.255)), Port::OUTPUT, module, Uncertain::OUT_QUANTIZED_2N)); addInput(Port::create(Vec(lft_x, yncscape(28.407, 8.255)), Port::INPUT, module, Uncertain::CLOCK_STORED)); addInput(Port::create(Vec(lft_x, yncscape(10.882, 8.255)), Port::INPUT, module, Uncertain::IN_STORED)); addInput(Port::create(Vec(mm2px(23.591), yncscape(10.882, 8.255)), Port::INPUT, module, Uncertain::IN_CURVEAMP)); addParam(ParamWidget::create(Vec(mm2px(16.285), yncscape(19.010, 9.525)), module, Uncertain::STORED_AMT, Uncertain::MIN_VOLTAGE + 2.5, Uncertain::MAX_VOLTAGE - 2.5, 5.0)); addParam(ParamWidget::create(Vec(mm2px(35.150), yncscape(19.010, 9.525)), module, Uncertain::CURVEAMP_AMT, 0.0,2.0,1.0)); addOutput(Port::create(Vec(rgt_x, yncscape(28.407, 8.255)), Port::OUTPUT, module, Uncertain::OUT_STORED_RND)); addOutput(Port::create(Vec(rgt_x, yncscape(10.882, 8.255)), Port::OUTPUT, module, Uncertain::OUT_STORED_BELL)); } } // namespace rack_plugin_TheXOR using namespace rack_plugin_TheXOR; RACK_PLUGIN_MODEL_INIT(TheXOR, Uncertain) { return Model::create("TheXOR", "Uncertain", "Uncertain", RANDOM_TAG); }