| @@ -21,7 +21,6 @@ void init(rack::Plugin *p) { | |||
| p->addModel(modelBlinds); | |||
| p->addModel(modelVeils); | |||
| p->addModel(modelFrames); | |||
| // p->addModel(modelPeaks); | |||
| p->addModel(modelMarbles); | |||
| p->addModel(modelStages); | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| #include "rack0.hpp" | |||
| #include "rack.hpp" | |||
| using namespace rack; | |||
| @@ -21,6 +21,5 @@ extern Model *modelBranches; | |||
| extern Model *modelBlinds; | |||
| extern Model *modelVeils; | |||
| extern Model *modelFrames; | |||
| extern Model *modelPeaks; | |||
| extern Model *modelStages; | |||
| extern Model *modelMarbles; | |||
| @@ -43,25 +43,35 @@ struct Blinds : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| Blinds() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||
| void step() override; | |||
| Blinds() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Blinds::GAIN1_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Blinds::GAIN2_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Blinds::GAIN3_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Blinds::GAIN4_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Blinds::MOD1_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Blinds::MOD2_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Blinds::MOD3_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Blinds::MOD4_PARAM, -1.0, 1.0, 0.0); | |||
| } | |||
| void process(const ProcessArgs &args) override; | |||
| }; | |||
| void Blinds::step() { | |||
| void Blinds::process(const ProcessArgs &args) { | |||
| float out = 0.0; | |||
| for (int i = 0; i < 4; i++) { | |||
| float g = params[GAIN1_PARAM + i].value; | |||
| g += params[MOD1_PARAM + i].value * inputs[CV1_INPUT + i].value / 5.0; | |||
| float g = params[GAIN1_PARAM + i].getValue(); | |||
| g += params[MOD1_PARAM + i].getValue() * inputs[CV1_INPUT + i].getVoltage() / 5.0; | |||
| g = clamp(g, -2.0f, 2.0f); | |||
| lights[CV1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, g)); | |||
| lights[CV1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -g)); | |||
| out += g * inputs[IN1_INPUT + i].normalize(5.0); | |||
| lights[OUT1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, out / 5.0)); | |||
| lights[OUT1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -out / 5.0)); | |||
| if (outputs[OUT1_OUTPUT + i].active) { | |||
| outputs[OUT1_OUTPUT + i].value = out; | |||
| lights[CV1_POS_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, g), args.sampleTime); | |||
| lights[CV1_NEG_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, -g), args.sampleTime); | |||
| out += g * inputs[IN1_INPUT + i].getNormalVoltage(5.0); | |||
| lights[OUT1_POS_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, out / 5.0), args.sampleTime); | |||
| lights[OUT1_NEG_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, -out / 5.0), args.sampleTime); | |||
| if (outputs[OUT1_OUTPUT + i].isConnected()) { | |||
| outputs[OUT1_OUTPUT + i].setVoltage(out); | |||
| out = 0.0; | |||
| } | |||
| } | |||
| @@ -69,38 +79,39 @@ void Blinds::step() { | |||
| struct BlindsWidget : ModuleWidget { | |||
| BlindsWidget(Blinds *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Blinds.svg"))); | |||
| BlindsWidget(Blinds *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Blinds.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(150, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(150, 365))); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 52), module, Blinds::GAIN1_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 131), module, Blinds::GAIN2_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 210), module, Blinds::GAIN3_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 288), module, Blinds::GAIN4_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(72, 63), module, Blinds::MOD1_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(72, 142), module, Blinds::MOD2_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(72, 221), module, Blinds::MOD3_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(72, 300), module, Blinds::MOD4_PARAM, -1.0, 1.0, 0.0)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 41), PortWidget::INPUT, module, Blinds::IN1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 120), PortWidget::INPUT, module, Blinds::IN2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 198), PortWidget::INPUT, module, Blinds::IN3_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 277), PortWidget::INPUT, module, Blinds::IN4_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 80), PortWidget::INPUT, module, Blinds::CV1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 159), PortWidget::INPUT, module, Blinds::CV2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 238), PortWidget::INPUT, module, Blinds::CV3_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 316), PortWidget::INPUT, module, Blinds::CV4_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(144, 41), PortWidget::OUTPUT, module, Blinds::OUT1_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(144, 120), PortWidget::OUTPUT, module, Blinds::OUT2_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(144, 198), PortWidget::OUTPUT, module, Blinds::OUT3_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(144, 277), PortWidget::OUTPUT, module, Blinds::OUT4_OUTPUT)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 52), module, Blinds::GAIN1_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 131), module, Blinds::GAIN2_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 210), module, Blinds::GAIN3_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 288), module, Blinds::GAIN4_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(72, 63), module, Blinds::MOD1_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(72, 142), module, Blinds::MOD2_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(72, 221), module, Blinds::MOD3_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(72, 300), module, Blinds::MOD4_PARAM)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 41), module, Blinds::IN1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 120), module, Blinds::IN2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 198), module, Blinds::IN3_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 277), module, Blinds::IN4_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 80), module, Blinds::CV1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 159), module, Blinds::CV2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 238), module, Blinds::CV3_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 316), module, Blinds::CV4_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(144, 41), module, Blinds::OUT1_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(144, 120), module, Blinds::OUT2_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(144, 198), module, Blinds::OUT3_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(144, 277), module, Blinds::OUT4_OUTPUT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(78, 96), module, Blinds::CV1_POS_LIGHT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(78, 175), module, Blinds::CV2_POS_LIGHT)); | |||
| @@ -33,13 +33,35 @@ struct Braids : Module { | |||
| braids::VcoJitterSource jitter_source; | |||
| braids::SignatureWaveshaper ws; | |||
| SampleRateConverter<1> src; | |||
| DoubleRingBuffer<Frame<1>, 256> outputBuffer; | |||
| dsp::SampleRateConverter<1> src; | |||
| dsp::DoubleRingBuffer<dsp::Frame<1>, 256> outputBuffer; | |||
| bool lastTrig = false; | |||
| bool lowCpu = false; | |||
| Braids(); | |||
| void step() override; | |||
| Braids() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); | |||
| configParam(Braids::SHAPE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Braids::FINE_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Braids::COARSE_PARAM, -2.0, 2.0, 0.0); | |||
| configParam(Braids::FM_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Braids::TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Braids::MODULATION_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Braids::COLOR_PARAM, 0.0, 1.0, 0.5); | |||
| memset(&osc, 0, sizeof(osc)); | |||
| osc.Init(); | |||
| memset(&jitter_source, 0, sizeof(jitter_source)); | |||
| jitter_source.Init(); | |||
| memset(&ws, 0, sizeof(ws)); | |||
| ws.Init(0x0000); | |||
| memset(&settings, 0, sizeof(settings)); | |||
| // List of supported settings | |||
| settings.meta_modulation = 0; | |||
| settings.vco_drift = 0; | |||
| settings.signature = 0; | |||
| } | |||
| void process(const ProcessArgs &args) override; | |||
| void setShape(int shape); | |||
| json_t *dataToJson() override { | |||
| @@ -77,24 +99,9 @@ struct Braids : Module { | |||
| }; | |||
| Braids::Braids() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||
| memset(&osc, 0, sizeof(osc)); | |||
| osc.Init(); | |||
| memset(&jitter_source, 0, sizeof(jitter_source)); | |||
| jitter_source.Init(); | |||
| memset(&ws, 0, sizeof(ws)); | |||
| ws.Init(0x0000); | |||
| memset(&settings, 0, sizeof(settings)); | |||
| // List of supported settings | |||
| settings.meta_modulation = 0; | |||
| settings.vco_drift = 0; | |||
| settings.signature = 0; | |||
| } | |||
| void Braids::step() { | |||
| void Braids::process(const ProcessArgs &args) { | |||
| // Trigger | |||
| bool trig = inputs[TRIG_INPUT].value >= 1.0; | |||
| bool trig = inputs[TRIG_INPUT].getVoltage() >= 1.0; | |||
| if (!lastTrig && trig) { | |||
| osc.Strike(); | |||
| } | |||
| @@ -102,10 +109,10 @@ void Braids::step() { | |||
| // Render frames | |||
| if (outputBuffer.empty()) { | |||
| float fm = params[FM_PARAM].value * inputs[FM_INPUT].value; | |||
| float fm = params[FM_PARAM].getValue() * inputs[FM_INPUT].getVoltage(); | |||
| // Set shape | |||
| int shape = roundf(params[SHAPE_PARAM].value * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | |||
| int shape = roundf(params[SHAPE_PARAM].getValue() * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | |||
| if (settings.meta_modulation) { | |||
| shape += roundf(fm / 10.0 * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | |||
| } | |||
| @@ -115,18 +122,18 @@ void Braids::step() { | |||
| osc.set_shape((braids::MacroOscillatorShape) settings.shape); | |||
| // Set timbre/modulation | |||
| float timbre = params[TIMBRE_PARAM].value + params[MODULATION_PARAM].value * inputs[TIMBRE_INPUT].value / 5.0; | |||
| float modulation = params[COLOR_PARAM].value + inputs[COLOR_INPUT].value / 5.0; | |||
| float timbre = params[TIMBRE_PARAM].getValue() + params[MODULATION_PARAM].getValue() * inputs[TIMBRE_INPUT].getVoltage() / 5.0; | |||
| float modulation = params[COLOR_PARAM].getValue() + inputs[COLOR_INPUT].getVoltage() / 5.0; | |||
| int16_t param1 = rescale(clamp(timbre, 0.0f, 1.0f), 0.0f, 1.0f, 0, INT16_MAX); | |||
| int16_t param2 = rescale(clamp(modulation, 0.0f, 1.0f), 0.0f, 1.0f, 0, INT16_MAX); | |||
| osc.set_parameters(param1, param2); | |||
| // Set pitch | |||
| float pitchV = inputs[PITCH_INPUT].value + params[COARSE_PARAM].value + params[FINE_PARAM].value / 12.0; | |||
| float pitchV = inputs[PITCH_INPUT].getVoltage() + params[COARSE_PARAM].getValue() + params[FINE_PARAM].getValue() / 12.0; | |||
| if (!settings.meta_modulation) | |||
| pitchV += fm; | |||
| if (lowCpu) | |||
| pitchV += log2f(96000.f * engineGetSampleTime()); | |||
| pitchV += log2f(96000.f * args.sampleTime); | |||
| int32_t pitch = (pitchV * 12.0 + 60) * 128; | |||
| pitch += jitter_source.Render(settings.vco_drift); | |||
| pitch = clamp(pitch, 0, 16383); | |||
| @@ -149,18 +156,18 @@ void Braids::step() { | |||
| if (lowCpu) { | |||
| for (int i = 0; i < 24; i++) { | |||
| Frame<1> f; | |||
| dsp::Frame<1> f; | |||
| f.samples[0] = render_buffer[i] / 32768.0; | |||
| outputBuffer.push(f); | |||
| } | |||
| } | |||
| else { | |||
| // Sample rate convert | |||
| Frame<1> in[24]; | |||
| dsp::Frame<1> in[24]; | |||
| for (int i = 0; i < 24; i++) { | |||
| in[i].samples[0] = render_buffer[i] / 32768.0; | |||
| } | |||
| src.setRates(96000, engineGetSampleRate()); | |||
| src.setRates(96000, args.sampleRate); | |||
| int inLen = 24; | |||
| int outLen = outputBuffer.capacity(); | |||
| @@ -171,8 +178,8 @@ void Braids::step() { | |||
| // Output | |||
| if (!outputBuffer.empty()) { | |||
| Frame<1> f = outputBuffer.shift(); | |||
| outputs[OUT_OUTPUT].value = 5.0 * f.samples[0]; | |||
| dsp::Frame<1> f = outputBuffer.shift(); | |||
| outputs[OUT_OUTPUT].setVoltage(5.0 * f.samples[0]); | |||
| } | |||
| } | |||
| @@ -233,33 +240,33 @@ struct BraidsDisplay : TransparentWidget { | |||
| std::shared_ptr<Font> font; | |||
| BraidsDisplay() { | |||
| font = Font::load(assetPlugin(pluginInstance, "res/hdad-segment14-1.002/Segment14.ttf")); | |||
| font = APP->window->loadFont(asset::plugin(pluginInstance, "res/hdad-segment14-1.002/Segment14.ttf")); | |||
| } | |||
| void draw(NVGcontext *vg) override { | |||
| void draw(const DrawArgs &args) override { | |||
| int shape = module ? module->settings.shape : 0; | |||
| // Background | |||
| NVGcolor backgroundColor = nvgRGB(0x38, 0x38, 0x38); | |||
| NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10); | |||
| nvgBeginPath(vg); | |||
| nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 5.0); | |||
| nvgFillColor(vg, backgroundColor); | |||
| nvgFill(vg); | |||
| nvgStrokeWidth(vg, 1.0); | |||
| nvgStrokeColor(vg, borderColor); | |||
| nvgStroke(vg); | |||
| nvgFontSize(vg, 36); | |||
| nvgFontFaceId(vg, font->handle); | |||
| nvgTextLetterSpacing(vg, 2.5); | |||
| nvgBeginPath(args.vg); | |||
| nvgRoundedRect(args.vg, 0.0, 0.0, box.size.x, box.size.y, 5.0); | |||
| nvgFillColor(args.vg, backgroundColor); | |||
| nvgFill(args.vg); | |||
| nvgStrokeWidth(args.vg, 1.0); | |||
| nvgStrokeColor(args.vg, borderColor); | |||
| nvgStroke(args.vg); | |||
| nvgFontSize(args.vg, 36); | |||
| nvgFontFaceId(args.vg, font->handle); | |||
| nvgTextLetterSpacing(args.vg, 2.5); | |||
| Vec textPos = Vec(10, 48); | |||
| NVGcolor textColor = nvgRGB(0xaf, 0xd2, 0x2c); | |||
| nvgFillColor(vg, nvgTransRGBA(textColor, 16)); | |||
| nvgText(vg, textPos.x, textPos.y, "~~~~", NULL); | |||
| nvgFillColor(vg, textColor); | |||
| nvgText(vg, textPos.x, textPos.y, algo_values[shape], NULL); | |||
| nvgFillColor(args.vg, nvgTransRGBA(textColor, 16)); | |||
| nvgText(args.vg, textPos.x, textPos.y, "~~~~", NULL); | |||
| nvgFillColor(args.vg, textColor); | |||
| nvgText(args.vg, textPos.x, textPos.y, algo_values[shape], NULL); | |||
| } | |||
| }; | |||
| @@ -291,8 +298,9 @@ struct BraidsLowCpuItem : MenuItem { | |||
| struct BraidsWidget : ModuleWidget { | |||
| BraidsWidget(Braids *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Braids.svg"))); | |||
| BraidsWidget(Braids *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Braids.svg"))); | |||
| { | |||
| BraidsDisplay *display = new BraidsDisplay(); | |||
| @@ -307,22 +315,22 @@ struct BraidsWidget : ModuleWidget { | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(210, 365))); | |||
| addParam(createParam<Rogan2SGray>(Vec(176, 59), module, Braids::SHAPE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan2SGray>(Vec(176, 59), module, Braids::SHAPE_PARAM)); | |||
| addParam(createParam<Rogan2PSWhite>(Vec(19, 138), module, Braids::FINE_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan2PSWhite>(Vec(97, 138), module, Braids::COARSE_PARAM, -2.0, 2.0, 0.0)); | |||
| addParam(createParam<Rogan2PSWhite>(Vec(176, 138), module, Braids::FM_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan2PSWhite>(Vec(19, 138), module, Braids::FINE_PARAM)); | |||
| addParam(createParam<Rogan2PSWhite>(Vec(97, 138), module, Braids::COARSE_PARAM)); | |||
| addParam(createParam<Rogan2PSWhite>(Vec(176, 138), module, Braids::FM_PARAM)); | |||
| addParam(createParam<Rogan2PSGreen>(Vec(19, 217), module, Braids::TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan2PSGreen>(Vec(97, 217), module, Braids::MODULATION_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan2PSRed>(Vec(176, 217), module, Braids::COLOR_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan2PSGreen>(Vec(19, 217), module, Braids::TIMBRE_PARAM)); | |||
| addParam(createParam<Rogan2PSGreen>(Vec(97, 217), module, Braids::MODULATION_PARAM)); | |||
| addParam(createParam<Rogan2PSRed>(Vec(176, 217), module, Braids::COLOR_PARAM)); | |||
| addInput(createPort<PJ301MPort>(Vec(10, 316), PortWidget::INPUT, module, Braids::TRIG_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(47, 316), PortWidget::INPUT, module, Braids::PITCH_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(84, 316), PortWidget::INPUT, module, Braids::FM_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(122, 316), PortWidget::INPUT, module, Braids::TIMBRE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(160, 316), PortWidget::INPUT, module, Braids::COLOR_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(205, 316), PortWidget::OUTPUT, module, Braids::OUT_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(10, 316), module, Braids::TRIG_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(47, 316), module, Braids::PITCH_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(84, 316), module, Braids::FM_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(122, 316), module, Braids::TIMBRE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(160, 316), module, Braids::COLOR_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(205, 316), module, Braids::OUT_OUTPUT)); | |||
| } | |||
| void appendContextMenu(Menu *menu) override { | |||
| @@ -31,12 +31,18 @@ struct Branches : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| SchmittTrigger gateTriggers[2]; | |||
| SchmittTrigger modeTriggers[2]; | |||
| dsp::SchmittTrigger gateTriggers[2]; | |||
| dsp::SchmittTrigger modeTriggers[2]; | |||
| bool modes[2] = {}; | |||
| bool outcomes[2] = {}; | |||
| Branches() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||
| Branches() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Branches::THRESHOLD1_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Branches::MODE1_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Branches::THRESHOLD2_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Branches::MODE2_PARAM, 0.0, 1.0, 0.0); | |||
| } | |||
| json_t *dataToJson() override { | |||
| json_t *rootJ = json_object(); | |||
| @@ -59,7 +65,7 @@ struct Branches : Module { | |||
| } | |||
| } | |||
| void step() override; | |||
| void process(const ProcessArgs &args) override; | |||
| void onReset() override { | |||
| for (int i = 0; i < 2; i++) { | |||
| @@ -70,20 +76,20 @@ struct Branches : Module { | |||
| }; | |||
| void Branches::step() { | |||
| void Branches::process(const ProcessArgs &args) { | |||
| float gate = 0.0; | |||
| for (int i = 0; i < 2; i++) { | |||
| // mode button | |||
| if (modeTriggers[i].process(params[MODE1_PARAM + i].value)) | |||
| if (modeTriggers[i].process(params[MODE1_PARAM + i].getValue())) | |||
| modes[i] = !modes[i]; | |||
| if (inputs[IN1_INPUT + i].active) | |||
| gate = inputs[IN1_INPUT + i].value; | |||
| if (inputs[IN1_INPUT + i].isConnected()) | |||
| gate = inputs[IN1_INPUT + i].getVoltage(); | |||
| if (gateTriggers[i].process(gate)) { | |||
| // trigger | |||
| float r = randomUniform(); | |||
| float threshold = clamp(params[THRESHOLD1_PARAM + i].value + inputs[P1_INPUT + i].value / 10.f, 0.f, 1.f); | |||
| float r = random::uniform(); | |||
| float threshold = clamp(params[THRESHOLD1_PARAM + i].getValue() + inputs[P1_INPUT + i].getVoltage() / 10.f, 0.f, 1.f); | |||
| bool toss = (r < threshold); | |||
| if (!modes[i]) { | |||
| // direct modes | |||
| @@ -100,36 +106,37 @@ void Branches::step() { | |||
| lights[STATE1_NEG_LIGHT + 2*i].value = 1.0; | |||
| } | |||
| lights[STATE1_POS_LIGHT + 2*i].value *= 1.0 - engineGetSampleTime() * 15.0; | |||
| lights[STATE1_NEG_LIGHT + 2*i].value *= 1.0 - engineGetSampleTime() * 15.0; | |||
| lights[STATE1_POS_LIGHT + 2*i].value *= 1.0 - args.sampleTime * 15.0; | |||
| lights[STATE1_NEG_LIGHT + 2*i].value *= 1.0 - args.sampleTime * 15.0; | |||
| lights[MODE1_LIGHT + i].value = modes[i] ? 1.0 : 0.0; | |||
| outputs[OUT1A_OUTPUT + i].value = outcomes[i] ? 0.0 : gate; | |||
| outputs[OUT1B_OUTPUT + i].value = outcomes[i] ? gate : 0.0; | |||
| outputs[OUT1A_OUTPUT + i].setVoltage(outcomes[i] ? 0.0 : gate); | |||
| outputs[OUT1B_OUTPUT + i].setVoltage(outcomes[i] ? gate : 0.0); | |||
| } | |||
| } | |||
| struct BranchesWidget : ModuleWidget { | |||
| BranchesWidget(Branches *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Branches.svg"))); | |||
| BranchesWidget(Branches *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Branches.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addParam(createParam<Rogan1PSRed>(Vec(24, 64), module, Branches::THRESHOLD1_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<TL1105>(Vec(69, 58), module, Branches::MODE1_PARAM, 0.0, 1.0, 0.0)); | |||
| addInput(createPort<PJ301MPort>(Vec(9, 122), PortWidget::INPUT, module, Branches::IN1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(55, 122), PortWidget::INPUT, module, Branches::P1_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(9, 160), PortWidget::OUTPUT, module, Branches::OUT1A_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(55, 160), PortWidget::OUTPUT, module, Branches::OUT1B_OUTPUT)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(24, 220), module, Branches::THRESHOLD2_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<TL1105>(Vec(69, 214), module, Branches::MODE2_PARAM, 0.0, 1.0, 0.0)); | |||
| addInput(createPort<PJ301MPort>(Vec(9, 278), PortWidget::INPUT, module, Branches::IN2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(55, 278), PortWidget::INPUT, module, Branches::P2_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(9, 316), PortWidget::OUTPUT, module, Branches::OUT2A_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(55, 316), PortWidget::OUTPUT, module, Branches::OUT2B_OUTPUT)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(24, 64), module, Branches::THRESHOLD1_PARAM)); | |||
| addParam(createParam<TL1105>(Vec(69, 58), module, Branches::MODE1_PARAM)); | |||
| addInput(createInput<PJ301MPort>(Vec(9, 122), module, Branches::IN1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(55, 122), module, Branches::P1_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(9, 160), module, Branches::OUT1A_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(55, 160), module, Branches::OUT1B_OUTPUT)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(24, 220), module, Branches::THRESHOLD2_PARAM)); | |||
| addParam(createParam<TL1105>(Vec(69, 214), module, Branches::MODE2_PARAM)); | |||
| addInput(createInput<PJ301MPort>(Vec(9, 278), module, Branches::IN2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(55, 278), module, Branches::P2_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(9, 316), module, Branches::OUT2A_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(55, 316), module, Branches::OUT2B_OUTPUT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(40, 169), module, Branches::STATE1_POS_LIGHT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(40, 325), module, Branches::STATE2_POS_LIGHT)); | |||
| @@ -46,10 +46,10 @@ struct Clouds : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| SampleRateConverter<2> inputSrc; | |||
| SampleRateConverter<2> outputSrc; | |||
| DoubleRingBuffer<Frame<2>, 256> inputBuffer; | |||
| DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||
| dsp::SampleRateConverter<2> inputSrc; | |||
| dsp::SampleRateConverter<2> outputSrc; | |||
| dsp::DoubleRingBuffer<dsp::Frame<2>, 256> inputBuffer; | |||
| dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||
| uint8_t *block_mem; | |||
| uint8_t *block_ccm; | |||
| @@ -57,9 +57,9 @@ struct Clouds : Module { | |||
| bool triggered = false; | |||
| SchmittTrigger freezeTrigger; | |||
| dsp::SchmittTrigger freezeTrigger; | |||
| bool freeze = false; | |||
| SchmittTrigger blendTrigger; | |||
| dsp::SchmittTrigger blendTrigger; | |||
| int blendMode = 0; | |||
| clouds::PlaybackMode playback; | |||
| @@ -67,7 +67,7 @@ struct Clouds : Module { | |||
| Clouds(); | |||
| ~Clouds(); | |||
| void step() override; | |||
| void process(const ProcessArgs &args) override; | |||
| void onReset() override { | |||
| freeze = false; | |||
| @@ -105,7 +105,22 @@ struct Clouds : Module { | |||
| }; | |||
| Clouds::Clouds() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Clouds::Clouds() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Clouds::POSITION_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Clouds::SIZE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Clouds::PITCH_PARAM, -2.0, 2.0, 0.0); | |||
| configParam(Clouds::IN_GAIN_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Clouds::DENSITY_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Clouds::TEXTURE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Clouds::BLEND_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Clouds::SPREAD_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Clouds::FEEDBACK_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Clouds::REVERB_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Clouds::FREEZE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Clouds::MODE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Clouds::LOAD_PARAM, 0.0, 1.0, 0.0); | |||
| const int memLen = 118784; | |||
| const int ccmLen = 65536 - 128; | |||
| block_mem = new uint8_t[memLen](); | |||
| @@ -123,24 +138,24 @@ Clouds::~Clouds() { | |||
| delete[] block_ccm; | |||
| } | |||
| void Clouds::step() { | |||
| void Clouds::process(const ProcessArgs &args) { | |||
| // Get input | |||
| Frame<2> inputFrame = {}; | |||
| dsp::Frame<2> inputFrame = {}; | |||
| if (!inputBuffer.full()) { | |||
| inputFrame.samples[0] = inputs[IN_L_INPUT].value * params[IN_GAIN_PARAM].value / 5.0; | |||
| inputFrame.samples[1] = inputs[IN_R_INPUT].active ? inputs[IN_R_INPUT].value * params[IN_GAIN_PARAM].value / 5.0 : inputFrame.samples[0]; | |||
| inputFrame.samples[0] = inputs[IN_L_INPUT].getVoltage() * params[IN_GAIN_PARAM].getValue() / 5.0; | |||
| inputFrame.samples[1] = inputs[IN_R_INPUT].isConnected() ? inputs[IN_R_INPUT].getVoltage() * params[IN_GAIN_PARAM].getValue() / 5.0 : inputFrame.samples[0]; | |||
| inputBuffer.push(inputFrame); | |||
| } | |||
| if (freezeTrigger.process(params[FREEZE_PARAM].value)) { | |||
| if (freezeTrigger.process(params[FREEZE_PARAM].getValue())) { | |||
| freeze ^= true; | |||
| } | |||
| if (blendTrigger.process(params[MODE_PARAM].value)) { | |||
| if (blendTrigger.process(params[MODE_PARAM].getValue())) { | |||
| blendMode = (blendMode + 1) % 4; | |||
| } | |||
| // Trigger | |||
| if (inputs[TRIG_INPUT].value >= 1.0) { | |||
| if (inputs[TRIG_INPUT].getVoltage() >= 1.0) { | |||
| triggered = true; | |||
| } | |||
| @@ -149,8 +164,8 @@ void Clouds::step() { | |||
| clouds::ShortFrame input[32] = {}; | |||
| // Convert input buffer | |||
| { | |||
| inputSrc.setRates(engineGetSampleRate(), 32000); | |||
| Frame<2> inputFrames[32]; | |||
| inputSrc.setRates(args.sampleRate, 32000); | |||
| dsp::Frame<2> inputFrames[32]; | |||
| int inLen = inputBuffer.size(); | |||
| int outLen = 32; | |||
| inputSrc.process(inputBuffer.startData(), &inLen, inputFrames, &outLen); | |||
| @@ -171,19 +186,19 @@ void Clouds::step() { | |||
| clouds::Parameters *p = processor->mutable_parameters(); | |||
| p->trigger = triggered; | |||
| p->gate = triggered; | |||
| p->freeze = freeze || (inputs[FREEZE_INPUT].value >= 1.0); | |||
| p->position = clamp(params[POSITION_PARAM].value + inputs[POSITION_INPUT].value / 5.0f, 0.0f, 1.0f); | |||
| p->size = clamp(params[SIZE_PARAM].value + inputs[SIZE_INPUT].value / 5.0f, 0.0f, 1.0f); | |||
| p->pitch = clamp((params[PITCH_PARAM].value + inputs[PITCH_INPUT].value) * 12.0f, -48.0f, 48.0f); | |||
| p->density = clamp(params[DENSITY_PARAM].value + inputs[DENSITY_INPUT].value / 5.0f, 0.0f, 1.0f); | |||
| p->texture = clamp(params[TEXTURE_PARAM].value + inputs[TEXTURE_INPUT].value / 5.0f, 0.0f, 1.0f); | |||
| p->dry_wet = params[BLEND_PARAM].value; | |||
| p->stereo_spread = params[SPREAD_PARAM].value; | |||
| p->feedback = params[FEEDBACK_PARAM].value; | |||
| p->freeze = freeze || (inputs[FREEZE_INPUT].getVoltage() >= 1.0); | |||
| p->position = clamp(params[POSITION_PARAM].getValue() + inputs[POSITION_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||
| p->size = clamp(params[SIZE_PARAM].getValue() + inputs[SIZE_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||
| p->pitch = clamp((params[PITCH_PARAM].getValue() + inputs[PITCH_INPUT].getVoltage()) * 12.0f, -48.0f, 48.0f); | |||
| p->density = clamp(params[DENSITY_PARAM].getValue() + inputs[DENSITY_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||
| p->texture = clamp(params[TEXTURE_PARAM].getValue() + inputs[TEXTURE_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||
| p->dry_wet = params[BLEND_PARAM].getValue(); | |||
| p->stereo_spread = params[SPREAD_PARAM].getValue(); | |||
| p->feedback = params[FEEDBACK_PARAM].getValue(); | |||
| // TODO | |||
| // Why doesn't dry audio get reverbed? | |||
| p->reverb = params[REVERB_PARAM].value; | |||
| float blend = inputs[BLEND_INPUT].value / 5.0f; | |||
| p->reverb = params[REVERB_PARAM].getValue(); | |||
| float blend = inputs[BLEND_INPUT].getVoltage() / 5.0f; | |||
| switch (blendMode) { | |||
| case 0: | |||
| p->dry_wet += blend; | |||
| @@ -208,13 +223,13 @@ void Clouds::step() { | |||
| // Convert output buffer | |||
| { | |||
| Frame<2> outputFrames[32]; | |||
| dsp::Frame<2> outputFrames[32]; | |||
| for (int i = 0; i < 32; i++) { | |||
| outputFrames[i].samples[0] = output[i].l / 32768.0; | |||
| outputFrames[i].samples[1] = output[i].r / 32768.0; | |||
| } | |||
| outputSrc.setRates(32000, engineGetSampleRate()); | |||
| outputSrc.setRates(32000, args.sampleRate); | |||
| int inLen = 32; | |||
| int outLen = outputBuffer.capacity(); | |||
| outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | |||
| @@ -225,28 +240,28 @@ void Clouds::step() { | |||
| } | |||
| // Set output | |||
| Frame<2> outputFrame = {}; | |||
| dsp::Frame<2> outputFrame = {}; | |||
| if (!outputBuffer.empty()) { | |||
| outputFrame = outputBuffer.shift(); | |||
| outputs[OUT_L_OUTPUT].value = 5.0 * outputFrame.samples[0]; | |||
| outputs[OUT_R_OUTPUT].value = 5.0 * outputFrame.samples[1]; | |||
| outputs[OUT_L_OUTPUT].setVoltage(5.0 * outputFrame.samples[0]); | |||
| outputs[OUT_R_OUTPUT].setVoltage(5.0 * outputFrame.samples[1]); | |||
| } | |||
| // Lights | |||
| clouds::Parameters *p = processor->mutable_parameters(); | |||
| VUMeter vuMeter; | |||
| dsp::VuMeter vuMeter; | |||
| vuMeter.dBInterval = 6.0; | |||
| Frame<2> lightFrame = p->freeze ? outputFrame : inputFrame; | |||
| dsp::Frame<2> lightFrame = p->freeze ? outputFrame : inputFrame; | |||
| vuMeter.setValue(fmaxf(fabsf(lightFrame.samples[0]), fabsf(lightFrame.samples[1]))); | |||
| lights[FREEZE_LIGHT].setBrightness(p->freeze ? 0.75 : 0.0); | |||
| lights[MIX_GREEN_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(3)); | |||
| lights[PAN_GREEN_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(2)); | |||
| lights[FEEDBACK_GREEN_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(1)); | |||
| lights[MIX_GREEN_LIGHT].setSmoothBrightness(vuMeter.getBrightness(3), args.sampleTime); | |||
| lights[PAN_GREEN_LIGHT].setSmoothBrightness(vuMeter.getBrightness(2), args.sampleTime); | |||
| lights[FEEDBACK_GREEN_LIGHT].setSmoothBrightness(vuMeter.getBrightness(1), args.sampleTime); | |||
| lights[REVERB_GREEN_LIGHT].setBrightness(0.0); | |||
| lights[MIX_RED_LIGHT].setBrightness(0.0); | |||
| lights[PAN_RED_LIGHT].setBrightness(0.0); | |||
| lights[FEEDBACK_RED_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(1)); | |||
| lights[REVERB_RED_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(0)); | |||
| lights[FEEDBACK_RED_LIGHT].setSmoothBrightness(vuMeter.getBrightness(1), args.sampleTime); | |||
| lights[REVERB_RED_LIGHT].setSmoothBrightness(vuMeter.getBrightness(0), args.sampleTime); | |||
| } | |||
| @@ -254,7 +269,7 @@ void Clouds::step() { | |||
| struct FreezeLight : YellowLight { | |||
| FreezeLight() { | |||
| box.size = Vec(28-6, 28-6); | |||
| bgColor = COLOR_BLACK_TRANSPARENT; | |||
| bgColor = color::BLACK_TRANSPARENT; | |||
| } | |||
| }; | |||
| @@ -304,47 +319,48 @@ struct CloudsWidget : ModuleWidget { | |||
| ParamWidget *feedbackParam; | |||
| ParamWidget *reverbParam; | |||
| CloudsWidget(Clouds *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Clouds.svg"))); | |||
| CloudsWidget(Clouds *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Clouds.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(240, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(240, 365))); | |||
| addParam(createParam<Rogan3PSRed>(Vec(27, 93), module, Clouds::POSITION_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan3PSGreen>(Vec(108, 93), module, Clouds::SIZE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(190, 93), module, Clouds::PITCH_PARAM, -2.0, 2.0, 0.0)); | |||
| addParam(createParam<Rogan3PSRed>(Vec(27, 93), module, Clouds::POSITION_PARAM)); | |||
| addParam(createParam<Rogan3PSGreen>(Vec(108, 93), module, Clouds::SIZE_PARAM)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(190, 93), module, Clouds::PITCH_PARAM)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(14, 180), module, Clouds::IN_GAIN_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(81, 180), module, Clouds::DENSITY_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(146, 180), module, Clouds::TEXTURE_PARAM, 0.0, 1.0, 0.5)); | |||
| blendParam = createParam<Rogan1PSWhite>(Vec(213, 180), module, Clouds::BLEND_PARAM, 0.0, 1.0, 0.5); | |||
| addParam(createParam<Rogan1PSRed>(Vec(14, 180), module, Clouds::IN_GAIN_PARAM)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(81, 180), module, Clouds::DENSITY_PARAM)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(146, 180), module, Clouds::TEXTURE_PARAM)); | |||
| blendParam = createParam<Rogan1PSWhite>(Vec(213, 180), module, Clouds::BLEND_PARAM); | |||
| addParam(blendParam); | |||
| spreadParam = createParam<Rogan1PSRed>(Vec(213, 180), module, Clouds::SPREAD_PARAM, 0.0, 1.0, 0.0); | |||
| spreadParam = createParam<Rogan1PSRed>(Vec(213, 180), module, Clouds::SPREAD_PARAM); | |||
| addParam(spreadParam); | |||
| feedbackParam = createParam<Rogan1PSGreen>(Vec(213, 180), module, Clouds::FEEDBACK_PARAM, 0.0, 1.0, 0.0); | |||
| feedbackParam = createParam<Rogan1PSGreen>(Vec(213, 180), module, Clouds::FEEDBACK_PARAM); | |||
| addParam(feedbackParam); | |||
| reverbParam = createParam<Rogan1PSBlue>(Vec(213, 180), module, Clouds::REVERB_PARAM, 0.0, 1.0, 0.0); | |||
| reverbParam = createParam<Rogan1PSBlue>(Vec(213, 180), module, Clouds::REVERB_PARAM); | |||
| addParam(reverbParam); | |||
| addParam(createParam<CKD6>(Vec(12, 43), module, Clouds::FREEZE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(Vec(211, 50), module, Clouds::MODE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(Vec(239, 50), module, Clouds::LOAD_PARAM, 0.0, 1.0, 0.0)); | |||
| addInput(createPort<PJ301MPort>(Vec(15, 274), PortWidget::INPUT, module, Clouds::FREEZE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(58, 274), PortWidget::INPUT, module, Clouds::TRIG_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(101, 274), PortWidget::INPUT, module, Clouds::POSITION_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(144, 274), PortWidget::INPUT, module, Clouds::SIZE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(188, 274), PortWidget::INPUT, module, Clouds::PITCH_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(230, 274), PortWidget::INPUT, module, Clouds::BLEND_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(15, 317), PortWidget::INPUT, module, Clouds::IN_L_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(58, 317), PortWidget::INPUT, module, Clouds::IN_R_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(101, 317), PortWidget::INPUT, module, Clouds::DENSITY_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(144, 317), PortWidget::INPUT, module, Clouds::TEXTURE_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(188, 317), PortWidget::OUTPUT, module, Clouds::OUT_L_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(230, 317), PortWidget::OUTPUT, module, Clouds::OUT_R_OUTPUT)); | |||
| addParam(createParam<CKD6>(Vec(12, 43), module, Clouds::FREEZE_PARAM)); | |||
| addParam(createParam<TL1105>(Vec(211, 50), module, Clouds::MODE_PARAM)); | |||
| addParam(createParam<TL1105>(Vec(239, 50), module, Clouds::LOAD_PARAM)); | |||
| addInput(createInput<PJ301MPort>(Vec(15, 274), module, Clouds::FREEZE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(58, 274), module, Clouds::TRIG_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(101, 274), module, Clouds::POSITION_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(144, 274), module, Clouds::SIZE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(188, 274), module, Clouds::PITCH_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(230, 274), module, Clouds::BLEND_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(15, 317), module, Clouds::IN_L_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(58, 317), module, Clouds::IN_R_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(101, 317), module, Clouds::DENSITY_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(144, 317), module, Clouds::TEXTURE_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(188, 317), module, Clouds::OUT_L_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(230, 317), module, Clouds::OUT_R_OUTPUT)); | |||
| addChild(createLight<FreezeLight>(Vec(12+3, 43+3), module, Clouds::FREEZE_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(Vec(82.5, 53), module, Clouds::MIX_GREEN_LIGHT)); | |||
| @@ -70,17 +70,17 @@ struct Elements : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| SampleRateConverter<2> inputSrc; | |||
| SampleRateConverter<2> outputSrc; | |||
| DoubleRingBuffer<Frame<2>, 256> inputBuffer; | |||
| DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||
| dsp::SampleRateConverter<2> inputSrc; | |||
| dsp::SampleRateConverter<2> outputSrc; | |||
| dsp::DoubleRingBuffer<dsp::Frame<2>, 256> inputBuffer; | |||
| dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||
| uint16_t reverb_buffer[32768] = {}; | |||
| elements::Part *part; | |||
| Elements(); | |||
| ~Elements(); | |||
| void step() override; | |||
| void process(const ProcessArgs &args) override; | |||
| json_t *dataToJson() override { | |||
| json_t *rootJ = json_object(); | |||
| @@ -105,7 +105,37 @@ struct Elements : Module { | |||
| }; | |||
| Elements::Elements() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Elements::Elements() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Elements::CONTOUR_PARAM, 0.0, 1.0, 1.0); | |||
| configParam(Elements::BOW_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Elements::BLOW_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Elements::STRIKE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::COARSE_PARAM, -30.0, 30.0, 0.0); | |||
| configParam(Elements::FINE_PARAM, -2.0, 2.0, 0.0); | |||
| configParam(Elements::FM_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::FLOW_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::MALLET_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::GEOMETRY_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::BRIGHTNESS_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::BOW_TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::BLOW_TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::STRIKE_TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::DAMPING_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::POSITION_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Elements::SPACE_PARAM, 0.0, 2.0, 0.0); | |||
| configParam(Elements::BOW_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::FLOW_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::BLOW_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::MALLET_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::STRIKE_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::DAMPING_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::GEOMETRY_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::POSITION_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::BRIGHTNESS_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Elements::SPACE_MOD_PARAM, -2.0, 2.0, 0.0); | |||
| configParam(Elements::PLAY_PARAM, 0.0, 1.0, 0.0); | |||
| part = new elements::Part(); | |||
| // In the Mutable Instruments code, Part doesn't initialize itself, so zero it here. | |||
| memset(part, 0, sizeof(*part)); | |||
| @@ -119,12 +149,12 @@ Elements::~Elements() { | |||
| delete part; | |||
| } | |||
| void Elements::step() { | |||
| void Elements::process(const ProcessArgs &args) { | |||
| // Get input | |||
| if (!inputBuffer.full()) { | |||
| Frame<2> inputFrame; | |||
| inputFrame.samples[0] = inputs[BLOW_INPUT].value / 5.0; | |||
| inputFrame.samples[1] = inputs[STRIKE_INPUT].value / 5.0; | |||
| dsp::Frame<2> inputFrame; | |||
| inputFrame.samples[0] = inputs[BLOW_INPUT].getVoltage() / 5.0; | |||
| inputFrame.samples[1] = inputs[STRIKE_INPUT].getVoltage() / 5.0; | |||
| inputBuffer.push(inputFrame); | |||
| } | |||
| @@ -137,8 +167,8 @@ void Elements::step() { | |||
| // Convert input buffer | |||
| { | |||
| inputSrc.setRates(engineGetSampleRate(), 32000); | |||
| Frame<2> inputFrames[16]; | |||
| inputSrc.setRates(args.sampleRate, 32000); | |||
| dsp::Frame<2> inputFrames[16]; | |||
| int inLen = inputBuffer.size(); | |||
| int outLen = 16; | |||
| inputSrc.process(inputBuffer.startData(), &inLen, inputFrames, &outLen); | |||
| @@ -152,12 +182,12 @@ void Elements::step() { | |||
| // Set patch from parameters | |||
| elements::Patch* p = part->mutable_patch(); | |||
| p->exciter_envelope_shape = params[CONTOUR_PARAM].value; | |||
| p->exciter_bow_level = params[BOW_PARAM].value; | |||
| p->exciter_blow_level = params[BLOW_PARAM].value; | |||
| p->exciter_strike_level = params[STRIKE_PARAM].value; | |||
| p->exciter_envelope_shape = params[CONTOUR_PARAM].getValue(); | |||
| p->exciter_bow_level = params[BOW_PARAM].getValue(); | |||
| p->exciter_blow_level = params[BLOW_PARAM].getValue(); | |||
| p->exciter_strike_level = params[STRIKE_PARAM].getValue(); | |||
| #define BIND(_p, _m, _i) clamp(params[_p].value + 3.3f*quadraticBipolar(params[_m].value)*inputs[_i].value/5.0f, 0.0f, 0.9995f) | |||
| #define BIND(_p, _m, _i) clamp(params[_p].getValue() + 3.3f*dsp::quadraticBipolar(params[_m].getValue())*inputs[_i].getVoltage()/5.0f, 0.0f, 0.9995f) | |||
| p->exciter_bow_timbre = BIND(BOW_TIMBRE_PARAM, BOW_TIMBRE_MOD_PARAM, BOW_TIMBRE_MOD_INPUT); | |||
| p->exciter_blow_meta = BIND(FLOW_PARAM, FLOW_MOD_PARAM, FLOW_MOD_INPUT); | |||
| @@ -168,27 +198,27 @@ void Elements::step() { | |||
| p->resonator_brightness = BIND(BRIGHTNESS_PARAM, BRIGHTNESS_MOD_PARAM, BRIGHTNESS_MOD_INPUT); | |||
| p->resonator_damping = BIND(DAMPING_PARAM, DAMPING_MOD_PARAM, DAMPING_MOD_INPUT); | |||
| p->resonator_position = BIND(POSITION_PARAM, POSITION_MOD_PARAM, POSITION_MOD_INPUT); | |||
| p->space = clamp(params[SPACE_PARAM].value + params[SPACE_MOD_PARAM].value*inputs[SPACE_MOD_INPUT].value/5.0f, 0.0f, 2.0f); | |||
| p->space = clamp(params[SPACE_PARAM].getValue() + params[SPACE_MOD_PARAM].getValue()*inputs[SPACE_MOD_INPUT].getVoltage()/5.0f, 0.0f, 2.0f); | |||
| // Get performance inputs | |||
| elements::PerformanceState performance; | |||
| performance.note = 12.0*inputs[NOTE_INPUT].value + roundf(params[COARSE_PARAM].value) + params[FINE_PARAM].value + 69.0; | |||
| performance.modulation = 3.3*quarticBipolar(params[FM_PARAM].value) * 49.5 * inputs[FM_INPUT].value/5.0; | |||
| performance.gate = params[PLAY_PARAM].value >= 1.0 || inputs[GATE_INPUT].value >= 1.0; | |||
| performance.strength = clamp(1.0 - inputs[STRENGTH_INPUT].value/5.0f, 0.0f, 1.0f); | |||
| performance.note = 12.0*inputs[NOTE_INPUT].getVoltage() + roundf(params[COARSE_PARAM].getValue()) + params[FINE_PARAM].getValue() + 69.0; | |||
| performance.modulation = 3.3*dsp::quarticBipolar(params[FM_PARAM].getValue()) * 49.5 * inputs[FM_INPUT].getVoltage()/5.0; | |||
| performance.gate = params[PLAY_PARAM].getValue() >= 1.0 || inputs[GATE_INPUT].getVoltage() >= 1.0; | |||
| performance.strength = clamp(1.0 - inputs[STRENGTH_INPUT].getVoltage()/5.0f, 0.0f, 1.0f); | |||
| // Generate audio | |||
| part->Process(performance, blow, strike, main, aux, 16); | |||
| // Convert output buffer | |||
| { | |||
| Frame<2> outputFrames[16]; | |||
| dsp::Frame<2> outputFrames[16]; | |||
| for (int i = 0; i < 16; i++) { | |||
| outputFrames[i].samples[0] = main[i]; | |||
| outputFrames[i].samples[1] = aux[i]; | |||
| } | |||
| outputSrc.setRates(32000, engineGetSampleRate()); | |||
| outputSrc.setRates(32000, args.sampleRate); | |||
| int inLen = 16; | |||
| int outLen = outputBuffer.capacity(); | |||
| outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | |||
| @@ -203,9 +233,9 @@ void Elements::step() { | |||
| // Set output | |||
| if (!outputBuffer.empty()) { | |||
| Frame<2> outputFrame = outputBuffer.shift(); | |||
| outputs[AUX_OUTPUT].value = 5.0 * outputFrame.samples[0]; | |||
| outputs[MAIN_OUTPUT].value = 5.0 * outputFrame.samples[1]; | |||
| dsp::Frame<2> outputFrame = outputBuffer.shift(); | |||
| outputs[AUX_OUTPUT].setVoltage(5.0 * outputFrame.samples[0]); | |||
| outputs[MAIN_OUTPUT].setVoltage(5.0 * outputFrame.samples[1]); | |||
| } | |||
| } | |||
| @@ -224,74 +254,75 @@ struct ElementsModalItem : MenuItem { | |||
| struct ElementsWidget : ModuleWidget { | |||
| ElementsWidget(Elements *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Elements.svg"))); | |||
| ElementsWidget(Elements *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Elements.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(480, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(480, 365))); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(28, 42), module, Elements::CONTOUR_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(99, 42), module, Elements::BOW_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(169, 42), module, Elements::BLOW_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(239, 42), module, Elements::STRIKE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(310, 42), module, Elements::COARSE_PARAM, -30.0, 30.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(381, 42), module, Elements::FINE_PARAM, -2.0, 2.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(451, 42), module, Elements::FM_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan3PSRed>(Vec(115, 116), module, Elements::FLOW_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan3PSGreen>(Vec(212, 116), module, Elements::MALLET_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(326, 116), module, Elements::GEOMETRY_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(423, 116), module, Elements::BRIGHTNESS_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(99, 202), module, Elements::BOW_TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(170, 202), module, Elements::BLOW_TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(239, 202), module, Elements::STRIKE_TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(310, 202), module, Elements::DAMPING_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(380, 202), module, Elements::POSITION_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(451, 202), module, Elements::SPACE_PARAM, 0.0, 2.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(104.5, 273), module, Elements::BOW_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(142.5, 273), module, Elements::FLOW_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(181.5, 273), module, Elements::BLOW_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(219.5, 273), module, Elements::MALLET_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(257.5, 273), module, Elements::STRIKE_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(315.5, 273), module, Elements::DAMPING_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(354.5, 273), module, Elements::GEOMETRY_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(392.5, 273), module, Elements::POSITION_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(430.5, 273), module, Elements::BRIGHTNESS_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(469.5, 273), module, Elements::SPACE_MOD_PARAM, -2.0, 2.0, 0.0)); | |||
| addInput(createPort<PJ301MPort>(Vec(20, 178), PortWidget::INPUT, module, Elements::NOTE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(55, 178), PortWidget::INPUT, module, Elements::FM_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(20, 224), PortWidget::INPUT, module, Elements::GATE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(55, 224), PortWidget::INPUT, module, Elements::STRENGTH_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(20, 270), PortWidget::INPUT, module, Elements::BLOW_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(55, 270), PortWidget::INPUT, module, Elements::STRIKE_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(20, 316), PortWidget::OUTPUT, module, Elements::AUX_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(55, 316), PortWidget::OUTPUT, module, Elements::MAIN_OUTPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(101, 316), PortWidget::INPUT, module, Elements::BOW_TIMBRE_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(139, 316), PortWidget::INPUT, module, Elements::FLOW_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(178, 316), PortWidget::INPUT, module, Elements::BLOW_TIMBRE_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(216, 316), PortWidget::INPUT, module, Elements::MALLET_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(254, 316), PortWidget::INPUT, module, Elements::STRIKE_TIMBRE_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(312, 316), PortWidget::INPUT, module, Elements::DAMPING_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(350, 316), PortWidget::INPUT, module, Elements::GEOMETRY_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(389, 316), PortWidget::INPUT, module, Elements::POSITION_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(427, 316), PortWidget::INPUT, module, Elements::BRIGHTNESS_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(466, 316), PortWidget::INPUT, module, Elements::SPACE_MOD_INPUT)); | |||
| addParam(createParam<CKD6>(Vec(36, 116), module, Elements::PLAY_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(28, 42), module, Elements::CONTOUR_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(99, 42), module, Elements::BOW_PARAM)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(169, 42), module, Elements::BLOW_PARAM)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(239, 42), module, Elements::STRIKE_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(310, 42), module, Elements::COARSE_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(381, 42), module, Elements::FINE_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(451, 42), module, Elements::FM_PARAM)); | |||
| addParam(createParam<Rogan3PSRed>(Vec(115, 116), module, Elements::FLOW_PARAM)); | |||
| addParam(createParam<Rogan3PSGreen>(Vec(212, 116), module, Elements::MALLET_PARAM)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(326, 116), module, Elements::GEOMETRY_PARAM)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(423, 116), module, Elements::BRIGHTNESS_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(99, 202), module, Elements::BOW_TIMBRE_PARAM)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(170, 202), module, Elements::BLOW_TIMBRE_PARAM)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(239, 202), module, Elements::STRIKE_TIMBRE_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(310, 202), module, Elements::DAMPING_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(380, 202), module, Elements::POSITION_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(451, 202), module, Elements::SPACE_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(104.5, 273), module, Elements::BOW_TIMBRE_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(142.5, 273), module, Elements::FLOW_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(181.5, 273), module, Elements::BLOW_TIMBRE_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(219.5, 273), module, Elements::MALLET_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(257.5, 273), module, Elements::STRIKE_TIMBRE_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(315.5, 273), module, Elements::DAMPING_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(354.5, 273), module, Elements::GEOMETRY_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(392.5, 273), module, Elements::POSITION_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(430.5, 273), module, Elements::BRIGHTNESS_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(469.5, 273), module, Elements::SPACE_MOD_PARAM)); | |||
| addInput(createInput<PJ301MPort>(Vec(20, 178), module, Elements::NOTE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(55, 178), module, Elements::FM_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(20, 224), module, Elements::GATE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(55, 224), module, Elements::STRENGTH_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(20, 270), module, Elements::BLOW_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(55, 270), module, Elements::STRIKE_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(20, 316), module, Elements::AUX_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(55, 316), module, Elements::MAIN_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(101, 316), module, Elements::BOW_TIMBRE_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(139, 316), module, Elements::FLOW_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(178, 316), module, Elements::BLOW_TIMBRE_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(216, 316), module, Elements::MALLET_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(254, 316), module, Elements::STRIKE_TIMBRE_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(312, 316), module, Elements::DAMPING_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(350, 316), module, Elements::GEOMETRY_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(389, 316), module, Elements::POSITION_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(427, 316), module, Elements::BRIGHTNESS_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(466, 316), module, Elements::SPACE_MOD_INPUT)); | |||
| addParam(createParam<CKD6>(Vec(36, 116), module, Elements::PLAY_PARAM)); | |||
| struct GateLight : YellowLight { | |||
| GateLight() { | |||
| box.size = Vec(28-6, 28-6); | |||
| bgColor = COLOR_BLACK_TRANSPARENT; | |||
| bgColor = color::BLACK_TRANSPARENT; | |||
| } | |||
| }; | |||
| @@ -46,11 +46,11 @@ struct Frames : Module { | |||
| bool poly_lfo_mode = false; | |||
| uint16_t lastControls[4] = {}; | |||
| SchmittTrigger addTrigger; | |||
| SchmittTrigger delTrigger; | |||
| dsp::SchmittTrigger addTrigger; | |||
| dsp::SchmittTrigger delTrigger; | |||
| Frames(); | |||
| void step() override; | |||
| void process(const ProcessArgs &args) override; | |||
| json_t *dataToJson() override { | |||
| json_t *rootJ = json_object(); | |||
| @@ -130,7 +130,18 @@ struct Frames : Module { | |||
| }; | |||
| Frames::Frames() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Frames::Frames() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Frames::GAIN1_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Frames::GAIN2_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Frames::GAIN3_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Frames::GAIN4_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Frames::FRAME_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Frames::MODULATION_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Frames::ADD_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Frames::DEL_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Frames::OFFSET_PARAM, 0.0, 1.0, 0.0); | |||
| memset(&keyframer, 0, sizeof(keyframer)); | |||
| keyframer.Init(); | |||
| memset(&poly_lfo, 0, sizeof(poly_lfo)); | |||
| @@ -140,15 +151,15 @@ Frames::Frames() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| } | |||
| void Frames::step() { | |||
| void Frames::process(const ProcessArgs &args) { | |||
| // Set gain and timestamp knobs | |||
| uint16_t controls[4]; | |||
| for (int i = 0; i < 4; i++) { | |||
| controls[i] = params[GAIN1_PARAM + i].value * 65535.0; | |||
| controls[i] = params[GAIN1_PARAM + i].getValue() * 65535.0; | |||
| } | |||
| int32_t timestamp = params[FRAME_PARAM].value * 65535.0; | |||
| int32_t timestampMod = timestamp + params[MODULATION_PARAM].value * inputs[FRAME_INPUT].value / 10.0 * 65535.0; | |||
| int32_t timestamp = params[FRAME_PARAM].getValue() * 65535.0; | |||
| int32_t timestampMod = timestamp + params[MODULATION_PARAM].getValue() * inputs[FRAME_INPUT].getVoltage() / 10.0 * 65535.0; | |||
| timestamp = clamp(timestamp, 0, 65535); | |||
| timestampMod = clamp(timestampMod, 0, 65535); | |||
| int16_t nearestIndex = -1; | |||
| @@ -182,12 +193,12 @@ void Frames::step() { | |||
| } | |||
| } | |||
| if (addTrigger.process(params[ADD_PARAM].value)) { | |||
| if (addTrigger.process(params[ADD_PARAM].getValue())) { | |||
| if (nearestIndex < 0) { | |||
| keyframer.AddKeyframe(timestamp, controls); | |||
| } | |||
| } | |||
| if (delTrigger.process(params[DEL_PARAM].value)) { | |||
| if (delTrigger.process(params[DEL_PARAM].getValue())) { | |||
| if (nearestIndex >= 0) { | |||
| int32_t nearestTimestamp = keyframer.keyframe(nearestIndex).timestamp; | |||
| keyframer.RemoveKeyframe(nearestTimestamp); | |||
| @@ -221,29 +232,29 @@ void Frames::step() { | |||
| } | |||
| // Get inputs | |||
| float all = ((int)params[OFFSET_PARAM].value == 1) ? 10.0 : 0.0; | |||
| if (inputs[ALL_INPUT].active) { | |||
| all = inputs[ALL_INPUT].value; | |||
| float all = ((int)params[OFFSET_PARAM].getValue() == 1) ? 10.0 : 0.0; | |||
| if (inputs[ALL_INPUT].isConnected()) { | |||
| all = inputs[ALL_INPUT].getVoltage(); | |||
| } | |||
| float ins[4]; | |||
| for (int i = 0; i < 4; i++) { | |||
| ins[i] = inputs[IN1_INPUT + i].normalize(all) * gains[i]; | |||
| ins[i] = inputs[IN1_INPUT + i].getNormalVoltage(all) * gains[i]; | |||
| } | |||
| // Set outputs | |||
| float mix = 0.0; | |||
| for (int i = 0; i < 4; i++) { | |||
| if (outputs[OUT1_OUTPUT + i].active) { | |||
| outputs[OUT1_OUTPUT + i].value = ins[i]; | |||
| if (outputs[OUT1_OUTPUT + i].isConnected()) { | |||
| outputs[OUT1_OUTPUT + i].setVoltage(ins[i]); | |||
| } | |||
| else { | |||
| mix += ins[i]; | |||
| } | |||
| } | |||
| outputs[MIX_OUTPUT].value = clamp(mix / 2.0, -10.0f, 10.0f); | |||
| outputs[MIX_OUTPUT].setVoltage(clamp(mix / 2.0, -10.0f, 10.0f)); | |||
| // Set lights | |||
| for (int i = 0; i < 4; i++) { | |||
| @@ -275,44 +286,45 @@ void Frames::step() { | |||
| struct CKSSRot : SVGSwitch { | |||
| CKSSRot() { | |||
| addFrame(SVG::load(assetPlugin(pluginInstance, "res/CKSS_rot_0.svg"))); | |||
| addFrame(SVG::load(assetPlugin(pluginInstance, "res/CKSS_rot_1.svg"))); | |||
| addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/CKSS_rot_0.svg"))); | |||
| addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/CKSS_rot_1.svg"))); | |||
| } | |||
| }; | |||
| struct FramesWidget : ModuleWidget { | |||
| FramesWidget(Frames *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Frames.svg"))); | |||
| FramesWidget(Frames *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Frames.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x-30, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x-30, 365))); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(14, 52), module, Frames::GAIN1_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(81, 52), module, Frames::GAIN2_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(149, 52), module, Frames::GAIN3_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(216, 52), module, Frames::GAIN4_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan6PSWhite>(Vec(89, 115), module, Frames::FRAME_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(208, 141), module, Frames::MODULATION_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<CKD6>(Vec(19, 123), module, Frames::ADD_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<CKD6>(Vec(19, 172), module, Frames::DEL_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<CKSSRot>(Vec(18, 239), module, Frames::OFFSET_PARAM, 0.0, 1.0, 0.0)); | |||
| addInput(createPort<PJ301MPort>(Vec(16, 273), PortWidget::INPUT, module, Frames::ALL_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(59, 273), PortWidget::INPUT, module, Frames::IN1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(102, 273), PortWidget::INPUT, module, Frames::IN2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(145, 273), PortWidget::INPUT, module, Frames::IN3_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(188, 273), PortWidget::INPUT, module, Frames::IN4_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(231, 273), PortWidget::INPUT, module, Frames::FRAME_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(16, 315), PortWidget::OUTPUT, module, Frames::MIX_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(59, 315), PortWidget::OUTPUT, module, Frames::OUT1_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(102, 315), PortWidget::OUTPUT, module, Frames::OUT2_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(145, 315), PortWidget::OUTPUT, module, Frames::OUT3_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(188, 315), PortWidget::OUTPUT, module, Frames::OUT4_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(231, 315), PortWidget::OUTPUT, module, Frames::FRAME_STEP_OUTPUT)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(14, 52), module, Frames::GAIN1_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(81, 52), module, Frames::GAIN2_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(149, 52), module, Frames::GAIN3_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(216, 52), module, Frames::GAIN4_PARAM)); | |||
| addParam(createParam<Rogan6PSWhite>(Vec(89, 115), module, Frames::FRAME_PARAM)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(208, 141), module, Frames::MODULATION_PARAM)); | |||
| addParam(createParam<CKD6>(Vec(19, 123), module, Frames::ADD_PARAM)); | |||
| addParam(createParam<CKD6>(Vec(19, 172), module, Frames::DEL_PARAM)); | |||
| addParam(createParam<CKSSRot>(Vec(18, 239), module, Frames::OFFSET_PARAM)); | |||
| addInput(createInput<PJ301MPort>(Vec(16, 273), module, Frames::ALL_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(59, 273), module, Frames::IN1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(102, 273), module, Frames::IN2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(145, 273), module, Frames::IN3_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(188, 273), module, Frames::IN4_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(231, 273), module, Frames::FRAME_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(16, 315), module, Frames::MIX_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(59, 315), module, Frames::OUT1_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(102, 315), module, Frames::OUT2_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(145, 315), module, Frames::OUT3_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(188, 315), module, Frames::OUT4_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(231, 315), module, Frames::FRAME_STEP_OUTPUT)); | |||
| addChild(createLight<SmallLight<GreenLight>>(Vec(30, 101), module, Frames::GAIN1_LIGHT + 0)); | |||
| addChild(createLight<SmallLight<GreenLight>>(Vec(97, 101), module, Frames::GAIN1_LIGHT + 1)); | |||
| @@ -328,9 +340,6 @@ struct FramesWidget : ModuleWidget { | |||
| addChild(createLight<FrameLight>(Vec(100, 126), module, Frames::FRAME_LIGHT)); | |||
| } | |||
| void appendContextMenu(Menu *menu) override { | |||
| Frames *frames = dynamic_cast<Frames*>(module); | |||
| assert(frames); | |||
| @@ -30,64 +30,66 @@ struct Kinks : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| SchmittTrigger trigger; | |||
| dsp::SchmittTrigger trigger; | |||
| float sample = 0.0; | |||
| Kinks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||
| void step() override; | |||
| Kinks() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);} | |||
| void process(const ProcessArgs &args) override; | |||
| }; | |||
| void Kinks::step() { | |||
| void Kinks::process(const ProcessArgs &args) { | |||
| // Gaussian noise generator | |||
| float noise = 2.0 * randomNormal(); | |||
| float noise = 2.0 * random::normal(); | |||
| // S&H | |||
| if (trigger.process(inputs[TRIG_INPUT].value / 0.7)) { | |||
| sample = inputs[SH_INPUT].normalize(noise); | |||
| if (trigger.process(inputs[TRIG_INPUT].getVoltage() / 0.7)) { | |||
| sample = inputs[SH_INPUT].getNormalVoltage(noise); | |||
| } | |||
| // lights | |||
| lights[SIGN_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, inputs[SIGN_INPUT].value / 5.0)); | |||
| lights[SIGN_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -inputs[SIGN_INPUT].value / 5.0)); | |||
| float logicSum = inputs[LOGIC_A_INPUT].value + inputs[LOGIC_B_INPUT].value; | |||
| lights[LOGIC_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, logicSum / 5.0)); | |||
| lights[LOGIC_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -logicSum / 5.0)); | |||
| lights[SIGN_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, inputs[SIGN_INPUT].getVoltage() / 5.0), args.sampleTime); | |||
| lights[SIGN_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -inputs[SIGN_INPUT].getVoltage() / 5.0), args.sampleTime); | |||
| float logicSum = inputs[LOGIC_A_INPUT].getVoltage() + inputs[LOGIC_B_INPUT].getVoltage(); | |||
| lights[LOGIC_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, logicSum / 5.0), args.sampleTime); | |||
| lights[LOGIC_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -logicSum / 5.0), args.sampleTime); | |||
| lights[SH_POS_LIGHT].setBrightness(fmaxf(0.0, sample / 5.0)); | |||
| lights[SH_NEG_LIGHT].setBrightness(fmaxf(0.0, -sample / 5.0)); | |||
| // outputs | |||
| outputs[INVERT_OUTPUT].value = -inputs[SIGN_INPUT].value; | |||
| outputs[HALF_RECTIFY_OUTPUT].value = fmaxf(0.0, inputs[SIGN_INPUT].value); | |||
| outputs[FULL_RECTIFY_OUTPUT].value = fabsf(inputs[SIGN_INPUT].value); | |||
| outputs[MAX_OUTPUT].value = fmaxf(inputs[LOGIC_A_INPUT].value, inputs[LOGIC_B_INPUT].value); | |||
| outputs[MIN_OUTPUT].value = fminf(inputs[LOGIC_A_INPUT].value, inputs[LOGIC_B_INPUT].value); | |||
| outputs[NOISE_OUTPUT].value = noise; | |||
| outputs[SH_OUTPUT].value = sample; | |||
| outputs[INVERT_OUTPUT].setVoltage(-inputs[SIGN_INPUT].getVoltage()); | |||
| outputs[HALF_RECTIFY_OUTPUT].setVoltage(fmaxf(0.0, inputs[SIGN_INPUT].getVoltage())); | |||
| outputs[FULL_RECTIFY_OUTPUT].setVoltage(fabsf(inputs[SIGN_INPUT].getVoltage())); | |||
| outputs[MAX_OUTPUT].setVoltage(fmaxf(inputs[LOGIC_A_INPUT].getVoltage(), inputs[LOGIC_B_INPUT].getVoltage())); | |||
| outputs[MIN_OUTPUT].setVoltage(fminf(inputs[LOGIC_A_INPUT].getVoltage(), inputs[LOGIC_B_INPUT].getVoltage())); | |||
| outputs[NOISE_OUTPUT].setVoltage(noise); | |||
| outputs[SH_OUTPUT].setVoltage(sample); | |||
| } | |||
| struct KinksWidget : ModuleWidget { | |||
| KinksWidget(Kinks *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Kinks.svg"))); | |||
| KinksWidget(Kinks *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Kinks.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addInput(createPort<PJ301MPort>(Vec(4, 75), PortWidget::INPUT, module, Kinks::SIGN_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(31, 75), PortWidget::OUTPUT, module, Kinks::INVERT_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(4, 113), PortWidget::OUTPUT, module, Kinks::HALF_RECTIFY_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(31, 113), PortWidget::OUTPUT, module, Kinks::FULL_RECTIFY_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(4, 75), module, Kinks::SIGN_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(31, 75), module, Kinks::INVERT_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(4, 113), module, Kinks::HALF_RECTIFY_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(31, 113), module, Kinks::FULL_RECTIFY_OUTPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(4, 177), PortWidget::INPUT, module, Kinks::LOGIC_A_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(31, 177), PortWidget::INPUT, module, Kinks::LOGIC_B_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(4, 214), PortWidget::OUTPUT, module, Kinks::MAX_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(31, 214), PortWidget::OUTPUT, module, Kinks::MIN_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(4, 177), module, Kinks::LOGIC_A_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(31, 177), module, Kinks::LOGIC_B_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(4, 214), module, Kinks::MAX_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(31, 214), module, Kinks::MIN_OUTPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(4, 278), PortWidget::INPUT, module, Kinks::SH_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(31, 278), PortWidget::INPUT, module, Kinks::TRIG_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(4, 316), PortWidget::OUTPUT, module, Kinks::NOISE_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(31, 316), PortWidget::OUTPUT, module, Kinks::SH_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(4, 278), module, Kinks::SH_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(31, 278), module, Kinks::TRIG_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(4, 316), module, Kinks::NOISE_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(31, 316), module, Kinks::SH_OUTPUT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(11, 59), module, Kinks::SIGN_POS_LIGHT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(11, 161), module, Kinks::LOGIC_POS_LIGHT)); | |||
| @@ -30,53 +30,55 @@ struct Links : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| Links() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||
| void step() override; | |||
| Links() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);} | |||
| void process(const ProcessArgs &args) override; | |||
| }; | |||
| void Links::step() { | |||
| float inA = inputs[A1_INPUT].value; | |||
| float inB = inputs[B1_INPUT].value + inputs[B2_INPUT].value; | |||
| float inC = inputs[C1_INPUT].value + inputs[C2_INPUT].value + inputs[C3_INPUT].value; | |||
| outputs[A1_OUTPUT].value = inA; | |||
| outputs[A2_OUTPUT].value = inA; | |||
| outputs[A3_OUTPUT].value = inA; | |||
| outputs[B1_OUTPUT].value = inB; | |||
| outputs[B2_OUTPUT].value = inB; | |||
| outputs[C1_OUTPUT].value = inC; | |||
| lights[A_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, inA / 5.0)); | |||
| lights[A_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -inA / 5.0)); | |||
| lights[B_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, inB / 5.0)); | |||
| lights[B_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -inB / 5.0)); | |||
| lights[C_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, inC / 5.0)); | |||
| lights[C_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -inC / 5.0)); | |||
| void Links::process(const ProcessArgs &args) { | |||
| float inA = inputs[A1_INPUT].getVoltage(); | |||
| float inB = inputs[B1_INPUT].getVoltage() + inputs[B2_INPUT].getVoltage(); | |||
| float inC = inputs[C1_INPUT].getVoltage() + inputs[C2_INPUT].getVoltage() + inputs[C3_INPUT].getVoltage(); | |||
| outputs[A1_OUTPUT].setVoltage(inA); | |||
| outputs[A2_OUTPUT].setVoltage(inA); | |||
| outputs[A3_OUTPUT].setVoltage(inA); | |||
| outputs[B1_OUTPUT].setVoltage(inB); | |||
| outputs[B2_OUTPUT].setVoltage(inB); | |||
| outputs[C1_OUTPUT].setVoltage(inC); | |||
| lights[A_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, inA / 5.0), args.sampleTime); | |||
| lights[A_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -inA / 5.0), args.sampleTime); | |||
| lights[B_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, inB / 5.0), args.sampleTime); | |||
| lights[B_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -inB / 5.0), args.sampleTime); | |||
| lights[C_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, inC / 5.0), args.sampleTime); | |||
| lights[C_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -inC / 5.0), args.sampleTime); | |||
| } | |||
| struct LinksWidget : ModuleWidget { | |||
| LinksWidget(Links *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Links.svg"))); | |||
| LinksWidget(Links *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Links.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addInput(createPort<PJ301MPort>(Vec(4, 75), PortWidget::INPUT, module, Links::A1_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(31, 75), PortWidget::OUTPUT, module, Links::A1_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(4, 113), PortWidget::OUTPUT, module, Links::A2_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(31, 113), PortWidget::OUTPUT, module, Links::A3_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(4, 75), module, Links::A1_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(31, 75), module, Links::A1_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(4, 113), module, Links::A2_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(31, 113), module, Links::A3_OUTPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(4, 177), PortWidget::INPUT, module, Links::B1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(31, 177), PortWidget::INPUT, module, Links::B2_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(4, 214), PortWidget::OUTPUT, module, Links::B1_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(31, 214), PortWidget::OUTPUT, module, Links::B2_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(4, 177), module, Links::B1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(31, 177), module, Links::B2_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(4, 214), module, Links::B1_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(31, 214), module, Links::B2_OUTPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(4, 278), PortWidget::INPUT, module, Links::C1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(31, 278), PortWidget::INPUT, module, Links::C2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(4, 316), PortWidget::INPUT, module, Links::C3_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(31, 316), PortWidget::OUTPUT, module, Links::C1_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(4, 278), module, Links::C1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(31, 278), module, Links::C2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(4, 316), module, Links::C3_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(31, 316), module, Links::C1_OUTPUT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(26, 59), module, Links::A_POS_LIGHT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(26, 161), module, Links::B_POS_LIGHT)); | |||
| @@ -193,13 +193,13 @@ struct Marbles : Module { | |||
| marbles::NoteFilter note_filter; | |||
| // State | |||
| BooleanTrigger tDejaVuTrigger; | |||
| BooleanTrigger xDejaVuTrigger; | |||
| BooleanTrigger tModeTrigger; | |||
| BooleanTrigger xModeTrigger; | |||
| BooleanTrigger tRangeTrigger; | |||
| BooleanTrigger xRangeTrigger; | |||
| BooleanTrigger externalTrigger; | |||
| dsp::BooleanTrigger tDejaVuTrigger; | |||
| dsp::BooleanTrigger xDejaVuTrigger; | |||
| dsp::BooleanTrigger tModeTrigger; | |||
| dsp::BooleanTrigger xModeTrigger; | |||
| dsp::BooleanTrigger tRangeTrigger; | |||
| dsp::BooleanTrigger xRangeTrigger; | |||
| dsp::BooleanTrigger externalTrigger; | |||
| bool t_deja_vu; | |||
| bool x_deja_vu; | |||
| int t_mode; | |||
| @@ -223,7 +223,24 @@ struct Marbles : Module { | |||
| float voltages[BLOCK_SIZE * 4] = {}; | |||
| int blockIndex = 0; | |||
| Marbles() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Marbles() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Marbles::T_DEJA_VU_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::X_DEJA_VU_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::DEJA_VU_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Marbles::T_RATE_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Marbles::X_SPREAD_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Marbles::T_MODE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::X_MODE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::DEJA_VU_LENGTH_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::T_BIAS_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Marbles::X_BIAS_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Marbles::T_RANGE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::X_RANGE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::EXTERNAL_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::T_JITTER_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Marbles::X_STEPS_PARAM, 0.0, 1.0, 0.5); | |||
| random_generator.Init(1); | |||
| random_stream.Init(&random_generator); | |||
| note_filter.Init(); | |||
| @@ -245,14 +262,14 @@ struct Marbles : Module { | |||
| } | |||
| void onRandomize() override { | |||
| t_mode = randomu32() % 3; | |||
| x_mode = randomu32() % 3; | |||
| t_range = randomu32() % 3; | |||
| x_range = randomu32() % 3; | |||
| t_mode = random::u32() % 3; | |||
| x_mode = random::u32() % 3; | |||
| t_range = random::u32() % 3; | |||
| x_range = random::u32() % 3; | |||
| } | |||
| void onSampleRateChange() override { | |||
| float sampleRate = engineGetSampleRate(); | |||
| float sampleRate = APP->engine->getSampleRate(); | |||
| t_generator.Init(&random_stream, sampleRate); | |||
| xy_generator.Init(&random_stream, sampleRate); | |||
| @@ -321,36 +338,36 @@ struct Marbles : Module { | |||
| x_clock_source_internal = json_integer_value(x_clock_source_internalJ); | |||
| } | |||
| void step() override { | |||
| void process(const ProcessArgs &args) override { | |||
| // Buttons | |||
| if (tDejaVuTrigger.process(params[T_DEJA_VU_PARAM].value <= 0.f)) { | |||
| if (tDejaVuTrigger.process(params[T_DEJA_VU_PARAM].getValue() <= 0.f)) { | |||
| t_deja_vu = !t_deja_vu; | |||
| } | |||
| if (xDejaVuTrigger.process(params[X_DEJA_VU_PARAM].value <= 0.f)) { | |||
| if (xDejaVuTrigger.process(params[X_DEJA_VU_PARAM].getValue() <= 0.f)) { | |||
| x_deja_vu = !x_deja_vu; | |||
| } | |||
| if (tModeTrigger.process(params[T_MODE_PARAM].value <= 0.f)) { | |||
| if (tModeTrigger.process(params[T_MODE_PARAM].getValue() <= 0.f)) { | |||
| t_mode = (t_mode + 1) % 3; | |||
| } | |||
| if (xModeTrigger.process(params[X_MODE_PARAM].value <= 0.f)) { | |||
| if (xModeTrigger.process(params[X_MODE_PARAM].getValue() <= 0.f)) { | |||
| x_mode = (x_mode + 1) % 3; | |||
| } | |||
| if (tRangeTrigger.process(params[T_RANGE_PARAM].value <= 0.f)) { | |||
| if (tRangeTrigger.process(params[T_RANGE_PARAM].getValue() <= 0.f)) { | |||
| t_range = (t_range + 1) % 3; | |||
| } | |||
| if (xRangeTrigger.process(params[X_RANGE_PARAM].value <= 0.f)) { | |||
| if (xRangeTrigger.process(params[X_RANGE_PARAM].getValue() <= 0.f)) { | |||
| x_range = (x_range + 1) % 3; | |||
| } | |||
| if (externalTrigger.process(params[EXTERNAL_PARAM].value <= 0.f)) { | |||
| if (externalTrigger.process(params[EXTERNAL_PARAM].getValue() <= 0.f)) { | |||
| external = !external; | |||
| } | |||
| // Clocks | |||
| bool t_gate = (inputs[T_CLOCK_INPUT].value >= 1.7f); | |||
| bool t_gate = (inputs[T_CLOCK_INPUT].getVoltage() >= 1.7f); | |||
| last_t_clock = stmlib::ExtractGateFlags(last_t_clock, t_gate); | |||
| t_clocks[blockIndex] = last_t_clock; | |||
| bool x_gate = (inputs[X_CLOCK_INPUT].value >= 1.7f); | |||
| bool x_gate = (inputs[X_CLOCK_INPUT].getVoltage() >= 1.7f); | |||
| last_xy_clock = stmlib::ExtractGateFlags(last_xy_clock, x_gate); | |||
| xy_clocks[blockIndex] = last_xy_clock; | |||
| @@ -379,21 +396,21 @@ struct Marbles : Module { | |||
| lights[EXTERNAL_LIGHT].setBrightness(external); | |||
| outputs[T1_OUTPUT].value = gates[blockIndex*2 + 0] ? 10.f : 0.f; | |||
| lights[T1_LIGHT].setBrightnessSmooth(gates[blockIndex*2 + 0]); | |||
| outputs[T2_OUTPUT].value = (ramp_master[blockIndex] < 0.5f) ? 10.f : 0.f; | |||
| lights[T2_LIGHT].setBrightnessSmooth(ramp_master[blockIndex] < 0.5f); | |||
| outputs[T3_OUTPUT].value = gates[blockIndex*2 + 1] ? 10.f : 0.f; | |||
| lights[T3_LIGHT].setBrightnessSmooth(gates[blockIndex*2 + 1]); | |||
| outputs[X1_OUTPUT].value = voltages[blockIndex*4 + 0]; | |||
| lights[X1_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 0]); | |||
| outputs[X2_OUTPUT].value = voltages[blockIndex*4 + 1]; | |||
| lights[X2_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 1]); | |||
| outputs[X3_OUTPUT].value = voltages[blockIndex*4 + 2]; | |||
| lights[X3_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 2]); | |||
| outputs[Y_OUTPUT].value = voltages[blockIndex*4 + 3]; | |||
| lights[Y_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 3]); | |||
| outputs[T1_OUTPUT].setVoltage(gates[blockIndex*2 + 0] ? 10.f : 0.f); | |||
| lights[T1_LIGHT].setSmoothBrightness(gates[blockIndex*2 + 0], args.sampleTime); | |||
| outputs[T2_OUTPUT].setVoltage((ramp_master[blockIndex] < 0.5f) ? 10.f : 0.f); | |||
| lights[T2_LIGHT].setSmoothBrightness(ramp_master[blockIndex] < 0.5f, args.sampleTime); | |||
| outputs[T3_OUTPUT].setVoltage(gates[blockIndex*2 + 1] ? 10.f : 0.f); | |||
| lights[T3_LIGHT].setSmoothBrightness(gates[blockIndex*2 + 1], args.sampleTime); | |||
| outputs[X1_OUTPUT].setVoltage(voltages[blockIndex*4 + 0]); | |||
| lights[X1_LIGHT].setSmoothBrightness(voltages[blockIndex*4 + 0], args.sampleTime); | |||
| outputs[X2_OUTPUT].setVoltage(voltages[blockIndex*4 + 1]); | |||
| lights[X2_LIGHT].setSmoothBrightness(voltages[blockIndex*4 + 1], args.sampleTime); | |||
| outputs[X3_OUTPUT].setVoltage(voltages[blockIndex*4 + 2]); | |||
| lights[X3_LIGHT].setSmoothBrightness(voltages[blockIndex*4 + 2], args.sampleTime); | |||
| outputs[Y_OUTPUT].setVoltage(voltages[blockIndex*4 + 3]); | |||
| lights[Y_LIGHT].setSmoothBrightness(voltages[blockIndex*4 + 3], args.sampleTime); | |||
| } | |||
| void stepBlock() { | |||
| @@ -405,7 +422,7 @@ struct Marbles : Module { | |||
| ramps.slave[0] = ramp_slave[0]; | |||
| ramps.slave[1] = ramp_slave[1]; | |||
| float deja_vu = clamp(params[DEJA_VU_PARAM].value + inputs[DEJA_VU_INPUT].value / 5.f, 0.f, 1.f); | |||
| float deja_vu = clamp(params[DEJA_VU_PARAM].getValue() + inputs[DEJA_VU_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||
| static const int loop_length[] = { | |||
| 1, 1, 1, 2, 2, | |||
| 2, 2, 2, 3, 3, | |||
| @@ -416,20 +433,20 @@ struct Marbles : Module { | |||
| 12, 12, 14, 14, 16, | |||
| 16 | |||
| }; | |||
| float deja_vu_length_index = params[DEJA_VU_LENGTH_PARAM].value * (LENGTHOF(loop_length) - 1); | |||
| float deja_vu_length_index = params[DEJA_VU_LENGTH_PARAM].getValue() * (LENGTHOF(loop_length) - 1); | |||
| int deja_vu_length = loop_length[(int) roundf(deja_vu_length_index)]; | |||
| // Set up TGenerator | |||
| bool t_external_clock = inputs[T_CLOCK_INPUT].active; | |||
| bool t_external_clock = inputs[T_CLOCK_INPUT].isConnected(); | |||
| t_generator.set_model((marbles::TGeneratorModel) t_mode); | |||
| t_generator.set_range((marbles::TGeneratorRange) t_range); | |||
| float t_rate = 60.f * (params[T_RATE_PARAM].value + inputs[T_RATE_INPUT].value / 5.f); | |||
| float t_rate = 60.f * (params[T_RATE_PARAM].getValue() + inputs[T_RATE_INPUT].getVoltage() / 5.f); | |||
| t_generator.set_rate(t_rate); | |||
| float t_bias = clamp(params[T_BIAS_PARAM].value + inputs[T_BIAS_INPUT].value / 5.f, 0.f, 1.f); | |||
| float t_bias = clamp(params[T_BIAS_PARAM].getValue() + inputs[T_BIAS_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||
| t_generator.set_bias(t_bias); | |||
| float t_jitter = clamp(params[T_JITTER_PARAM].value + inputs[T_JITTER_INPUT].value / 5.f, 0.f, 1.f); | |||
| float t_jitter = clamp(params[T_JITTER_PARAM].getValue() + inputs[T_JITTER_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||
| t_generator.set_jitter(t_jitter); | |||
| t_generator.set_deja_vu(t_deja_vu ? deja_vu : 0.f); | |||
| t_generator.set_length(deja_vu_length); | |||
| @@ -442,23 +459,23 @@ struct Marbles : Module { | |||
| // Set up XYGenerator | |||
| marbles::ClockSource x_clock_source = (marbles::ClockSource) x_clock_source_internal; | |||
| if (inputs[X_CLOCK_INPUT].active) | |||
| if (inputs[X_CLOCK_INPUT].isConnected()) | |||
| x_clock_source = marbles::CLOCK_SOURCE_EXTERNAL; | |||
| marbles::GroupSettings x; | |||
| x.control_mode = (marbles::ControlMode) x_mode; | |||
| x.voltage_range = (marbles::VoltageRange) x_range; | |||
| // TODO Fix the scaling | |||
| float note_cv = 0.5f * (params[X_SPREAD_PARAM].value + inputs[X_SPREAD_INPUT].value / 5.f); | |||
| float note_cv = 0.5f * (params[X_SPREAD_PARAM].getValue() + inputs[X_SPREAD_INPUT].getVoltage() / 5.f); | |||
| float u = note_filter.Process(0.5f * (note_cv + 1.f)); | |||
| x.register_mode = external; | |||
| x.register_value = u; | |||
| float x_spread = clamp(params[X_SPREAD_PARAM].value + inputs[X_SPREAD_INPUT].value / 5.f, 0.f, 1.f); | |||
| float x_spread = clamp(params[X_SPREAD_PARAM].getValue() + inputs[X_SPREAD_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||
| x.spread = x_spread; | |||
| float x_bias = clamp(params[X_BIAS_PARAM].value + inputs[X_BIAS_INPUT].value / 5.f, 0.f, 1.f); | |||
| float x_bias = clamp(params[X_BIAS_PARAM].getValue() + inputs[X_BIAS_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||
| x.bias = x_bias; | |||
| float x_steps = clamp(params[X_STEPS_PARAM].value + inputs[X_STEPS_INPUT].value / 5.f, 0.f, 1.f); | |||
| float x_steps = clamp(params[X_STEPS_PARAM].getValue() + inputs[X_STEPS_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||
| x.steps = x_steps; | |||
| x.deja_vu = x_deja_vu ? deja_vu : 0.f; | |||
| x.length = deja_vu_length; | |||
| @@ -509,29 +526,30 @@ struct CKD6Light : BASE { | |||
| struct MarblesWidget : ModuleWidget { | |||
| MarblesWidget(Marbles *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Marbles.svg"))); | |||
| MarblesWidget(Marbles *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Marbles.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addParam(createParamCentered<CKD6>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<CKD6>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 22.244)), module, Marbles::DEJA_VU_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(23.467, 35.264)), module, Marbles::T_RATE_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(67.945, 35.243)), module, Marbles::X_SPREAD_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(6.945, 38.794)), module, Marbles::T_MODE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(84.445, 38.793)), module, Marbles::X_MODE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 51.144)), module, Marbles::DEJA_VU_LENGTH_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(9.545, 58.394)), module, Marbles::T_BIAS_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(81.844, 58.394)), module, Marbles::X_BIAS_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(26.644, 59.694)), module, Marbles::T_RANGE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(64.744, 59.694)), module, Marbles::X_RANGE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(45.694, 67.294)), module, Marbles::EXTERNAL_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(31.544, 73.694)), module, Marbles::T_JITTER_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(59.845, 73.694)), module, Marbles::X_STEPS_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<CKD6>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_PARAM)); | |||
| addParam(createParamCentered<CKD6>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_PARAM)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 22.244)), module, Marbles::DEJA_VU_PARAM)); | |||
| addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(23.467, 35.264)), module, Marbles::T_RATE_PARAM)); | |||
| addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(67.945, 35.243)), module, Marbles::X_SPREAD_PARAM)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(6.945, 38.794)), module, Marbles::T_MODE_PARAM)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(84.445, 38.793)), module, Marbles::X_MODE_PARAM)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 51.144)), module, Marbles::DEJA_VU_LENGTH_PARAM)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(9.545, 58.394)), module, Marbles::T_BIAS_PARAM)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(81.844, 58.394)), module, Marbles::X_BIAS_PARAM)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(26.644, 59.694)), module, Marbles::T_RANGE_PARAM)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(64.744, 59.694)), module, Marbles::X_RANGE_PARAM)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(45.694, 67.294)), module, Marbles::EXTERNAL_PARAM)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(31.544, 73.694)), module, Marbles::T_JITTER_PARAM)); | |||
| addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(59.845, 73.694)), module, Marbles::X_STEPS_PARAM)); | |||
| addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 81.944)), module, Marbles::T_BIAS_INPUT)); | |||
| addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 81.944)), module, Marbles::X_BIAS_INPUT)); | |||
| @@ -1,659 +0,0 @@ | |||
| #include <chrono> | |||
| #include "peaks/io_buffer.h" | |||
| #include "peaks/processors.h" | |||
| #include "AudibleInstruments.hpp" | |||
| enum SwitchIndex { | |||
| SWITCH_TWIN_MODE, | |||
| SWITCH_FUNCTION, | |||
| SWITCH_GATE_TRIG_1, | |||
| SWITCH_GATE_TRIG_2 | |||
| }; | |||
| enum EditMode { | |||
| EDIT_MODE_TWIN, | |||
| EDIT_MODE_SPLIT, | |||
| EDIT_MODE_FIRST, | |||
| EDIT_MODE_SECOND, | |||
| EDIT_MODE_LAST | |||
| }; | |||
| enum Function { | |||
| FUNCTION_ENVELOPE, | |||
| FUNCTION_LFO, | |||
| FUNCTION_TAP_LFO, | |||
| FUNCTION_DRUM_GENERATOR, | |||
| FUNCTION_MINI_SEQUENCER, | |||
| FUNCTION_PULSE_SHAPER, | |||
| FUNCTION_PULSE_RANDOMIZER, | |||
| FUNCTION_FM_DRUM_GENERATOR, | |||
| FUNCTION_LAST, | |||
| FUNCTION_FIRST_ALTERNATE_FUNCTION = FUNCTION_MINI_SEQUENCER | |||
| }; | |||
| struct Settings { | |||
| uint8_t edit_mode; | |||
| uint8_t function[2]; | |||
| uint8_t pot_value[8]; | |||
| bool snap_mode; | |||
| }; | |||
| static const int32_t kLongPressDuration = 600; | |||
| static const uint8_t kNumAdcChannels = 4; | |||
| static const uint16_t kAdcThresholdUnlocked = 1 << (16 - 10); // 10 bits | |||
| static const uint16_t kAdcThresholdLocked = 1 << (16 - 8); // 8 bits | |||
| // Global scope, so variables can be accessed by process() function. | |||
| int16_t gOutputBuffer[peaks::kBlockSize]; | |||
| int16_t gBrightness[2] = {0, 0}; | |||
| static void set_led_brightness(int channel, int16_t value) { | |||
| gBrightness[channel] = value; | |||
| } | |||
| // File scope because of IOBuffer function signature. | |||
| // It cannot refer to a member function of class Peaks(). | |||
| static void process(peaks::IOBuffer::Block* block, size_t size) { | |||
| for (size_t i = 0; i < peaks::kNumChannels; ++i) { | |||
| // TODO | |||
| // processors[i].Process(block->input[i], gOutputBuffer, size); | |||
| set_led_brightness(i, gOutputBuffer[0]); | |||
| for (size_t j = 0; j < size; ++j) { | |||
| // From calibration_data.h, shifting signed to unsigned values. | |||
| int32_t shifted_value = 32767 + static_cast<int32_t>(gOutputBuffer[j]); | |||
| CONSTRAIN(shifted_value, 0, 65535); | |||
| block->output[i][j] = static_cast<uint16_t>(shifted_value); | |||
| } | |||
| } | |||
| } | |||
| struct Peaks : Module { | |||
| enum ParamIds { | |||
| KNOB_1_PARAM, | |||
| KNOB_2_PARAM, | |||
| KNOB_3_PARAM, | |||
| KNOB_4_PARAM, | |||
| BUTTON_1_PARAM, | |||
| BUTTON_2_PARAM, | |||
| TRIG_1_PARAM, | |||
| TRIG_2_PARAM, | |||
| NUM_PARAMS | |||
| }; | |||
| enum InputIds { | |||
| GATE_1_INPUT, | |||
| GATE_2_INPUT, | |||
| NUM_INPUTS | |||
| }; | |||
| enum OutputIds { | |||
| OUT_1_OUTPUT, | |||
| OUT_2_OUTPUT, | |||
| NUM_OUTPUTS | |||
| }; | |||
| enum LightIds { | |||
| TRIG_1_LIGHT, | |||
| TRIG_2_LIGHT, | |||
| TWIN_MODE_LIGHT, | |||
| FUNC_1_LIGHT, | |||
| FUNC_2_LIGHT, | |||
| FUNC_3_LIGHT, | |||
| FUNC_4_LIGHT, | |||
| NUM_LIGHTS | |||
| }; | |||
| static const peaks::ProcessorFunction function_table_[FUNCTION_LAST][2]; | |||
| EditMode edit_mode_ = EDIT_MODE_TWIN; | |||
| Function function_[2] = {FUNCTION_ENVELOPE, FUNCTION_ENVELOPE}; | |||
| Settings settings_; | |||
| uint8_t pot_value_[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | |||
| bool snap_mode_ = false; | |||
| bool snapped_[4] = {false, false, false, false}; | |||
| int32_t adc_lp_[kNumAdcChannels] = {0, 0, 0, 0}; | |||
| int32_t adc_value_[kNumAdcChannels] = {0, 0, 0, 0}; | |||
| int32_t adc_threshold_[kNumAdcChannels] = {0, 0, 0, 0}; | |||
| long long press_time_[2] = {0, 0}; | |||
| SchmittTrigger switches_[2]; | |||
| peaks::IOBuffer ioBuffer; | |||
| peaks::GateFlags gate_flags[2] = {0, 0}; | |||
| SampleRateConverter<2> outputSrc; | |||
| DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||
| bool initNumberStation = false; | |||
| peaks::Processors processors[2]; | |||
| Peaks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| settings_.edit_mode = EDIT_MODE_TWIN; | |||
| settings_.function[0] = FUNCTION_ENVELOPE; | |||
| settings_.function[1] = FUNCTION_ENVELOPE; | |||
| settings_.snap_mode = false; | |||
| std::fill(&settings_.pot_value[0], &settings_.pot_value[8], 0); | |||
| memset(&ioBuffer, 0, sizeof(ioBuffer)); | |||
| memset(&processors[0], 0, sizeof(processors[0])); | |||
| memset(&processors[1], 0, sizeof(processors[1])); | |||
| ioBuffer.Init(); | |||
| processors[0].Init(0); | |||
| processors[1].Init(1); | |||
| } | |||
| void onReset() override { | |||
| init(); | |||
| } | |||
| void init() { | |||
| std::fill(&pot_value_[0], &pot_value_[8], 0); | |||
| std::fill(&press_time_[0], &press_time_[1], 0); | |||
| std::fill(&gBrightness[0], &gBrightness[1], 0); | |||
| std::fill(&adc_lp_[0], &adc_lp_[kNumAdcChannels], 0); | |||
| std::fill(&adc_value_[0], &adc_value_[kNumAdcChannels], 0); | |||
| std::fill(&adc_threshold_[0], &adc_threshold_[kNumAdcChannels], 0); | |||
| std::fill(&snapped_[0], &snapped_[kNumAdcChannels], false); | |||
| edit_mode_ = static_cast<EditMode>(settings_.edit_mode); | |||
| function_[0] = static_cast<Function>(settings_.function[0]); | |||
| function_[1] = static_cast<Function>(settings_.function[1]); | |||
| std::copy(&settings_.pot_value[0], &settings_.pot_value[8], &pot_value_[0]); | |||
| if (edit_mode_ == EDIT_MODE_FIRST || edit_mode_ == EDIT_MODE_SECOND) { | |||
| lockPots(); | |||
| for (uint8_t i = 0; i < 4; ++i) { | |||
| processors[0].set_parameter( | |||
| i, | |||
| static_cast<uint16_t>(pot_value_[i]) << 8); | |||
| processors[1].set_parameter( | |||
| i, | |||
| static_cast<uint16_t>(pot_value_[i + 4]) << 8); | |||
| } | |||
| } | |||
| snap_mode_ = settings_.snap_mode; | |||
| changeControlMode(); | |||
| setFunction(0, function_[0]); | |||
| setFunction(1, function_[1]); | |||
| } | |||
| json_t *dataToJson() override { | |||
| saveState(); | |||
| json_t *rootJ = json_object(); | |||
| json_object_set_new(rootJ, "edit_mode", json_integer((int)settings_.edit_mode)); | |||
| json_object_set_new(rootJ, "fcn_channel_1", json_integer((int)settings_.function[0])); | |||
| json_object_set_new(rootJ, "fcn_channel_2", json_integer((int)settings_.function[1])); | |||
| json_t *potValuesJ = json_array(); | |||
| for (int p : pot_value_) { | |||
| json_t *pJ = json_integer(p); | |||
| json_array_append_new(potValuesJ, pJ); | |||
| } | |||
| json_object_set_new(rootJ, "pot_values", potValuesJ); | |||
| json_object_set_new(rootJ, "snap_mode", json_boolean(settings_.snap_mode)); | |||
| return rootJ; | |||
| } | |||
| void dataFromJson(json_t *rootJ) override { | |||
| json_t *editModeJ = json_object_get(rootJ, "edit_mode"); | |||
| if (editModeJ) { | |||
| settings_.edit_mode = static_cast<EditMode>(json_integer_value(editModeJ)); | |||
| } | |||
| json_t *fcnChannel1J = json_object_get(rootJ, "fcn_channel_1"); | |||
| if (fcnChannel1J) { | |||
| settings_.function[0] = static_cast<Function>(json_integer_value(fcnChannel1J)); | |||
| } | |||
| json_t *fcnChannel2J = json_object_get(rootJ, "fcn_channel_2"); | |||
| if (fcnChannel2J) { | |||
| settings_.function[1] = static_cast<Function>(json_integer_value(fcnChannel2J)); | |||
| } | |||
| json_t *snapModeJ = json_object_get(rootJ, "snap_mode"); | |||
| if (snapModeJ) { | |||
| settings_.snap_mode = json_boolean_value(snapModeJ); | |||
| } | |||
| json_t *potValuesJ = json_object_get(rootJ, "pot_values"); | |||
| size_t potValueId; | |||
| json_t *pJ; | |||
| json_array_foreach(potValuesJ, potValueId, pJ) { | |||
| if (potValueId < sizeof(pot_value_) / sizeof(pot_value_)[0]) { | |||
| settings_.pot_value[potValueId] = json_integer_value(pJ); | |||
| } | |||
| } | |||
| // Update module internal state from settings. | |||
| init(); | |||
| } | |||
| void step() override { | |||
| poll(); | |||
| pollPots(); | |||
| // Initialize "secret" number station mode. | |||
| if (initNumberStation) { | |||
| processors[0].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION); | |||
| processors[1].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION); | |||
| initNumberStation = false; | |||
| } | |||
| if (outputBuffer.empty()) { | |||
| ioBuffer.Process(::process); | |||
| uint32_t external_gate_inputs = 0; | |||
| external_gate_inputs |= (inputs[GATE_1_INPUT].value ? 1 : 0); | |||
| external_gate_inputs |= (inputs[GATE_2_INPUT].value ? 2 : 0); | |||
| uint32_t buttons = 0; | |||
| buttons |= (params[TRIG_1_PARAM].value ? 1 : 0); | |||
| buttons |= (params[TRIG_2_PARAM].value ? 2 : 0); | |||
| uint32_t gate_inputs = external_gate_inputs | buttons; | |||
| // Prepare sample rate conversion. | |||
| // Peaks is sampling at 48kHZ. | |||
| outputSrc.setRates(48000, engineGetSampleRate()); | |||
| int inLen = peaks::kBlockSize; | |||
| int outLen = outputBuffer.capacity(); | |||
| Frame<2> f[peaks::kBlockSize]; | |||
| // Process an entire block of data from the IOBuffer. | |||
| for (size_t k = 0; k < peaks::kBlockSize; ++k) { | |||
| peaks::IOBuffer::Slice slice = ioBuffer.NextSlice(1); | |||
| for (size_t i = 0; i < peaks::kNumChannels; ++i) { | |||
| gate_flags[i] = peaks::ExtractGateFlags( | |||
| gate_flags[i], | |||
| gate_inputs & (1 << i)); | |||
| f[k].samples[i] = slice.block->output[i][slice.frame_index]; | |||
| } | |||
| // A hack to make channel 1 aware of what's going on in channel 2. Used to | |||
| // reset the sequencer. | |||
| slice.block->input[0][slice.frame_index] = gate_flags[0] | (gate_flags[1] << 4) | (buttons & 8 ? peaks::GATE_FLAG_FROM_BUTTON : 0); | |||
| slice.block->input[1][slice.frame_index] = gate_flags[1] | (buttons & 2 ? peaks::GATE_FLAG_FROM_BUTTON : 0); | |||
| } | |||
| outputSrc.process(f, &inLen, outputBuffer.endData(), &outLen); | |||
| outputBuffer.endIncr(outLen); | |||
| } | |||
| // Update outputs. | |||
| if (!outputBuffer.empty()) { | |||
| Frame<2> f = outputBuffer.shift(); | |||
| // Peaks manual says output spec is 0..8V for envelopes and 10Vpp for audio/CV. | |||
| // TODO Check the output values against an actual device. | |||
| outputs[OUT_1_OUTPUT].value = rescale(static_cast<float>(f.samples[0]), 0.0f, 65535.f, -8.0f, 8.0f); | |||
| outputs[OUT_2_OUTPUT].value = rescale(static_cast<float>(f.samples[1]), 0.0f, 65535.f, -8.0f, 8.0f); | |||
| } | |||
| } | |||
| inline Function function() const { | |||
| return edit_mode_ == EDIT_MODE_SECOND ? function_[1] : function_[0]; | |||
| } | |||
| void changeControlMode(); | |||
| void setFunction(uint8_t index, Function f); | |||
| void onPotChanged(uint16_t id, uint16_t value); | |||
| void onSwitchReleased(uint16_t id, uint16_t data); | |||
| void saveState(); | |||
| void lockPots(); | |||
| void poll(); | |||
| void pollPots(); | |||
| void refreshLeds(); | |||
| long long getSystemTimeMs(); | |||
| }; | |||
| const peaks::ProcessorFunction Peaks::function_table_[FUNCTION_LAST][2] = { | |||
| { peaks::PROCESSOR_FUNCTION_ENVELOPE, peaks::PROCESSOR_FUNCTION_ENVELOPE }, | |||
| { peaks::PROCESSOR_FUNCTION_LFO, peaks::PROCESSOR_FUNCTION_LFO }, | |||
| { peaks::PROCESSOR_FUNCTION_TAP_LFO, peaks::PROCESSOR_FUNCTION_TAP_LFO }, | |||
| { peaks::PROCESSOR_FUNCTION_BASS_DRUM, peaks::PROCESSOR_FUNCTION_SNARE_DRUM }, | |||
| { peaks::PROCESSOR_FUNCTION_MINI_SEQUENCER, peaks::PROCESSOR_FUNCTION_MINI_SEQUENCER }, | |||
| { peaks::PROCESSOR_FUNCTION_PULSE_SHAPER, peaks::PROCESSOR_FUNCTION_PULSE_SHAPER }, | |||
| { peaks::PROCESSOR_FUNCTION_PULSE_RANDOMIZER, peaks::PROCESSOR_FUNCTION_PULSE_RANDOMIZER }, | |||
| { peaks::PROCESSOR_FUNCTION_FM_DRUM, peaks::PROCESSOR_FUNCTION_FM_DRUM }, | |||
| }; | |||
| void Peaks::changeControlMode() { | |||
| uint16_t parameters[4]; | |||
| for (int i = 0; i < 4; ++i) { | |||
| parameters[i] = adc_value_[i]; | |||
| } | |||
| if (edit_mode_ == EDIT_MODE_SPLIT) { | |||
| processors[0].CopyParameters(¶meters[0], 2); | |||
| processors[1].CopyParameters(¶meters[2], 2); | |||
| processors[0].set_control_mode(peaks::CONTROL_MODE_HALF); | |||
| processors[1].set_control_mode(peaks::CONTROL_MODE_HALF); | |||
| } | |||
| else if (edit_mode_ == EDIT_MODE_TWIN) { | |||
| processors[0].CopyParameters(¶meters[0], 4); | |||
| processors[1].CopyParameters(¶meters[0], 4); | |||
| processors[0].set_control_mode(peaks::CONTROL_MODE_FULL); | |||
| processors[1].set_control_mode(peaks::CONTROL_MODE_FULL); | |||
| } | |||
| else { | |||
| processors[0].set_control_mode(peaks::CONTROL_MODE_FULL); | |||
| processors[1].set_control_mode(peaks::CONTROL_MODE_FULL); | |||
| } | |||
| } | |||
| void Peaks::setFunction(uint8_t index, Function f) { | |||
| if (edit_mode_ == EDIT_MODE_SPLIT || edit_mode_ == EDIT_MODE_TWIN) { | |||
| function_[0] = function_[1] = f; | |||
| processors[0].set_function(function_table_[f][0]); | |||
| processors[1].set_function(function_table_[f][1]); | |||
| } | |||
| else { | |||
| function_[index] = f; | |||
| processors[index].set_function(function_table_[f][index]); | |||
| } | |||
| } | |||
| void Peaks::onSwitchReleased(uint16_t id, uint16_t data) { | |||
| switch (id) { | |||
| case SWITCH_TWIN_MODE: | |||
| if (data > kLongPressDuration) { | |||
| edit_mode_ = static_cast<EditMode>( | |||
| (edit_mode_ + EDIT_MODE_FIRST) % EDIT_MODE_LAST); | |||
| function_[0] = function_[1]; | |||
| processors[0].set_function(function_table_[function_[0]][0]); | |||
| processors[1].set_function(function_table_[function_[0]][1]); | |||
| lockPots(); | |||
| } | |||
| else { | |||
| if (edit_mode_ <= EDIT_MODE_SPLIT) { | |||
| edit_mode_ = static_cast<EditMode>(EDIT_MODE_SPLIT - edit_mode_); | |||
| } | |||
| else { | |||
| edit_mode_ = static_cast<EditMode>(EDIT_MODE_SECOND - (edit_mode_ & 1)); | |||
| lockPots(); | |||
| } | |||
| } | |||
| changeControlMode(); | |||
| saveState(); | |||
| break; | |||
| case SWITCH_FUNCTION: { | |||
| Function f = function(); | |||
| if (data > kLongPressDuration) { | |||
| f = static_cast<Function>((f + FUNCTION_FIRST_ALTERNATE_FUNCTION) % FUNCTION_LAST); | |||
| } | |||
| else { | |||
| if (f <= FUNCTION_DRUM_GENERATOR) { | |||
| f = static_cast<Function>((f + 1) & 3); | |||
| } | |||
| else { | |||
| f = static_cast<Function>(((f + 1) & 3) + FUNCTION_FIRST_ALTERNATE_FUNCTION); | |||
| } | |||
| } | |||
| setFunction(edit_mode_ - EDIT_MODE_FIRST, f); | |||
| saveState(); | |||
| } | |||
| break; | |||
| case SWITCH_GATE_TRIG_1: | |||
| // no-op | |||
| break; | |||
| case SWITCH_GATE_TRIG_2: | |||
| // no-op | |||
| break; | |||
| } | |||
| } | |||
| void Peaks::lockPots() { | |||
| std::fill( | |||
| &adc_threshold_[0], | |||
| &adc_threshold_[kNumAdcChannels], | |||
| kAdcThresholdLocked); | |||
| std::fill(&snapped_[0], &snapped_[kNumAdcChannels], false); | |||
| } | |||
| void Peaks::pollPots() { | |||
| for (uint8_t i = 0; i < kNumAdcChannels; ++i) { | |||
| adc_lp_[i] = (int32_t(params[KNOB_1_PARAM + i].value) + adc_lp_[i] * 7) >> 3; | |||
| int32_t value = adc_lp_[i]; | |||
| int32_t current_value = adc_value_[i]; | |||
| if (value >= current_value + adc_threshold_[i] || | |||
| value <= current_value - adc_threshold_[i] || | |||
| !adc_threshold_[i]) { | |||
| onPotChanged(i, value); | |||
| adc_value_[i] = value; | |||
| adc_threshold_[i] = kAdcThresholdUnlocked; | |||
| } | |||
| } | |||
| } | |||
| void Peaks::onPotChanged(uint16_t id, uint16_t value) { | |||
| switch (edit_mode_) { | |||
| case EDIT_MODE_TWIN: | |||
| processors[0].set_parameter(id, value); | |||
| processors[1].set_parameter(id, value); | |||
| pot_value_[id] = value >> 8; | |||
| break; | |||
| case EDIT_MODE_SPLIT: | |||
| if (id < 2) { | |||
| processors[0].set_parameter(id, value); | |||
| } | |||
| else { | |||
| processors[1].set_parameter(id - 2, value); | |||
| } | |||
| pot_value_[id] = value >> 8; | |||
| break; | |||
| case EDIT_MODE_FIRST: | |||
| case EDIT_MODE_SECOND: { | |||
| uint8_t index = id + (edit_mode_ - EDIT_MODE_FIRST) * 4; | |||
| peaks::Processors* p = &processors[edit_mode_ - EDIT_MODE_FIRST]; | |||
| int16_t delta = static_cast<int16_t>(pot_value_[index]) - \ | |||
| static_cast<int16_t>(value >> 8); | |||
| if (delta < 0) { | |||
| delta = -delta; | |||
| } | |||
| if (!snap_mode_ || snapped_[id] || delta <= 2) { | |||
| p->set_parameter(id, value); | |||
| pot_value_[index] = value >> 8; | |||
| snapped_[id] = true; | |||
| } | |||
| } | |||
| break; | |||
| case EDIT_MODE_LAST: | |||
| break; | |||
| } | |||
| } | |||
| long long Peaks::getSystemTimeMs() { | |||
| return std::chrono::duration_cast<std::chrono::milliseconds>( | |||
| std::chrono::steady_clock::now().time_since_epoch() | |||
| ).count(); | |||
| } | |||
| void Peaks::poll() { | |||
| for (uint8_t i = 0; i < 2; ++i) { | |||
| if (switches_[i].process(params[BUTTON_1_PARAM + i].value)) { | |||
| press_time_[i] = getSystemTimeMs(); | |||
| } | |||
| if (switches_[i].isHigh() && press_time_[i] != 0) { | |||
| int32_t pressed_time = getSystemTimeMs() - press_time_[i]; | |||
| if (pressed_time > kLongPressDuration) { | |||
| onSwitchReleased(SWITCH_TWIN_MODE + i, pressed_time); | |||
| press_time_[i] = 0; // Inhibit next release event | |||
| } | |||
| } | |||
| if (!switches_[i].isHigh() && press_time_[i] != 0) { | |||
| int32_t delta = getSystemTimeMs() - press_time_[i] + 1; | |||
| onSwitchReleased(SWITCH_TWIN_MODE + i, delta); | |||
| press_time_[i] = 0; // Not in original code! | |||
| } | |||
| } | |||
| refreshLeds(); | |||
| } | |||
| void Peaks::saveState() { | |||
| settings_.edit_mode = edit_mode_; | |||
| settings_.function[0] = function_[0]; | |||
| settings_.function[1] = function_[1]; | |||
| std::copy(&pot_value_[0], &pot_value_[8], &settings_.pot_value[0]); | |||
| settings_.snap_mode = snap_mode_; | |||
| } | |||
| void Peaks::refreshLeds() { | |||
| uint8_t flash = (getSystemTimeMs() >> 7) & 7; | |||
| switch (edit_mode_) { | |||
| case EDIT_MODE_FIRST: | |||
| lights[TWIN_MODE_LIGHT].value = (flash == 1) ? 1.0f : 0.0f; | |||
| break; | |||
| case EDIT_MODE_SECOND: | |||
| lights[TWIN_MODE_LIGHT].value = (flash == 1 || flash == 3) ? 1.0f : 0.0f; | |||
| break; | |||
| default: | |||
| lights[TWIN_MODE_LIGHT].value = (edit_mode_ & 1) ? 1.0f : 0.0f; | |||
| break; | |||
| } | |||
| if ((getSystemTimeMs() & 256) && function() >= FUNCTION_FIRST_ALTERNATE_FUNCTION) { | |||
| for (size_t i = 0; i < 4; ++i) { | |||
| lights[FUNC_1_LIGHT + i].value = 0.0f; | |||
| } | |||
| } | |||
| else { | |||
| for (size_t i = 0; i < 4; ++i) { | |||
| lights[FUNC_1_LIGHT + i].value = ((function() & 3) == i) ? 1.0f : 0.0f; | |||
| } | |||
| } | |||
| uint8_t b[2]; | |||
| for (uint8_t i = 0; i < 2; ++i) { | |||
| switch (function_[i]) { | |||
| case FUNCTION_DRUM_GENERATOR: | |||
| case FUNCTION_FM_DRUM_GENERATOR: | |||
| b[i] = (int16_t) std::abs(gBrightness[i]) >> 8; | |||
| b[i] = b[i] >= 255 ? 255 : b[i]; | |||
| break; | |||
| case FUNCTION_LFO: | |||
| case FUNCTION_TAP_LFO: | |||
| case FUNCTION_MINI_SEQUENCER: { | |||
| int32_t brightness = int32_t(gBrightness[i]) * 409 >> 8; | |||
| brightness += 32768; | |||
| brightness >>= 8; | |||
| CONSTRAIN(brightness, 0, 255); | |||
| b[i] = brightness; | |||
| } | |||
| break; | |||
| default: | |||
| b[i] = gBrightness[i] >> 7; | |||
| break; | |||
| } | |||
| } | |||
| if (processors[0].function() == peaks::PROCESSOR_FUNCTION_NUMBER_STATION) { | |||
| uint8_t pattern = processors[0].number_station().digit() | |||
| ^ processors[1].number_station().digit(); | |||
| for (size_t i = 0; i < 4; ++i) { | |||
| lights[FUNC_1_LIGHT + i].value = (pattern & 1) ? 1.0f : 0.0f; | |||
| pattern = pattern >> 1; | |||
| } | |||
| b[0] = processors[0].number_station().gate() ? 255 : 0; | |||
| b[1] = processors[1].number_station().gate() ? 255 : 0; | |||
| } | |||
| lights[TRIG_1_LIGHT].value = rescale(static_cast<float>(b[0]), 0.0f, 255.0f, 0.0f, 1.0f); | |||
| lights[TRIG_2_LIGHT].value = rescale(static_cast<float>(b[1]), 0.0f, 255.0f, 0.0f, 1.0f); | |||
| } | |||
| struct PeaksWidget : ModuleWidget { | |||
| PeaksWidget(Peaks *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Peaks.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addParam(createParam<TL1105>(Vec(8.5, 52), module, Peaks::BUTTON_1_PARAM, 0.0f, 1.0f, 0.0f)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 74), module, Peaks::TWIN_MODE_LIGHT)); | |||
| addParam(createParam<TL1105>(Vec(8.5, 89), module, Peaks::BUTTON_2_PARAM, 0.0f, 1.0f, 0.0f)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 111), module, Peaks::FUNC_1_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 126.75), module, Peaks::FUNC_2_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 142.5), module, Peaks::FUNC_3_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 158), module, Peaks::FUNC_4_LIGHT)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(61, 51), module, Peaks::KNOB_1_PARAM, 0.0f, 65535.0f, 16384.0f)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(61, 115), module, Peaks::KNOB_2_PARAM, 0.0f, 65535.0f, 16384.0f)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(61, 179), module, Peaks::KNOB_3_PARAM, 0.0f, 65535.0f, 32678.0f)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(61, 244), module, Peaks::KNOB_4_PARAM, 0.0f, 65535.0f, 32678.0f)); | |||
| addParam(createParam<LEDBezel>(Vec(11, 188), module, Peaks::TRIG_1_PARAM, 0.0f, 1.0f, 0.0f)); | |||
| addParam(createParam<LEDBezel>(Vec(11, 273), module, Peaks::TRIG_2_PARAM, 0.0f, 1.0f, 0.0f)); | |||
| addChild(createLight<LEDBezelLight<GreenLight>>(Vec(11, 188).plus(mm2px(Vec(0.75, 0.75))), module, Peaks::TRIG_1_LIGHT)); | |||
| addChild(createLight<LEDBezelLight<GreenLight>>(Vec(11, 273).plus(mm2px(Vec(0.75, 0.75))), module, Peaks::TRIG_2_LIGHT)); | |||
| addInput(createPort<PJ301MPort>(Vec(10, 230), PortWidget::INPUT, module, Peaks::GATE_1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(10, 315), PortWidget::INPUT, module, Peaks::GATE_2_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(53, 315), PortWidget::OUTPUT, module, Peaks::OUT_1_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(86, 315), PortWidget::OUTPUT, module, Peaks::OUT_2_OUTPUT)); | |||
| } | |||
| void appendContextMenu(Menu *menu) override { | |||
| Peaks *peaks = dynamic_cast<Peaks*>(this->module); | |||
| struct SnapModeItem : MenuItem { | |||
| Peaks *peaks; | |||
| void onAction(const event::Action &e) override { | |||
| peaks->snap_mode_ = !peaks->snap_mode_; | |||
| } | |||
| void step() override { | |||
| rightText = (peaks->snap_mode_) ? "âś”" : ""; | |||
| MenuItem::step(); | |||
| } | |||
| }; | |||
| struct NumberStationItem : MenuItem { | |||
| Peaks *peaks; | |||
| void onAction(const event::Action &e) override { | |||
| peaks->initNumberStation = true; | |||
| } | |||
| }; | |||
| menu->addChild(construct<MenuLabel>()); | |||
| menu->addChild(construct<SnapModeItem>(&SnapModeItem::text, "Snap Mode", &SnapModeItem::peaks, peaks)); | |||
| menu->addChild(construct<MenuLabel>()); | |||
| menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Secret Modes")); | |||
| menu->addChild(construct<NumberStationItem>(&NumberStationItem::text, "Number Station", &NumberStationItem::peaks, peaks)); | |||
| } | |||
| }; | |||
| Model *modelPeaks = createModel<Peaks, PeaksWidget>("Peaks"); | |||
| @@ -1,5 +1,11 @@ | |||
| #include "AudibleInstruments.hpp" | |||
| #pragma GCC diagnostic push | |||
| #ifndef __clang__ | |||
| #pragma GCC diagnostic ignored "-Wsuggest-override" | |||
| #endif | |||
| #include "plaits/dsp/voice.h" | |||
| #pragma GCC diagnostic pop | |||
| struct Plaits : Module { | |||
| @@ -42,15 +48,26 @@ struct Plaits : Module { | |||
| char shared_buffer[16384]; | |||
| float triPhase = 0.f; | |||
| SampleRateConverter<2> outputSrc; | |||
| DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||
| dsp::SampleRateConverter<2> outputSrc; | |||
| dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||
| bool lowCpu = false; | |||
| bool lpg = false; | |||
| SchmittTrigger model1Trigger; | |||
| SchmittTrigger model2Trigger; | |||
| dsp::SchmittTrigger model1Trigger; | |||
| dsp::SchmittTrigger model2Trigger; | |||
| Plaits() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Plaits::MODEL1_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Plaits::MODEL2_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Plaits::FREQ_PARAM, -4.0, 4.0, 0.0); | |||
| configParam(Plaits::HARMONICS_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Plaits::TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Plaits::MORPH_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Plaits::TIMBRE_CV_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Plaits::FREQ_CV_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Plaits::MORPH_CV_PARAM, -1.0, 1.0, 0.0); | |||
| Plaits() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| memset(shared_buffer, 0, sizeof(shared_buffer)); | |||
| stmlib::BufferAllocator allocator(shared_buffer, sizeof(shared_buffer)); | |||
| voice.Init(&allocator); | |||
| @@ -67,7 +84,7 @@ struct Plaits : Module { | |||
| } | |||
| void onRandomize() override { | |||
| patch.engine = randomu32() % 16; | |||
| patch.engine = random::u32() % 16; | |||
| } | |||
| json_t *dataToJson() override { | |||
| @@ -99,12 +116,12 @@ struct Plaits : Module { | |||
| patch.decay = json_number_value(decayJ); | |||
| } | |||
| void step() override { | |||
| void process(const ProcessArgs &args) override { | |||
| if (outputBuffer.empty()) { | |||
| const int blockSize = 12; | |||
| // Model buttons | |||
| if (model1Trigger.process(params[MODEL1_PARAM].value)) { | |||
| if (model1Trigger.process(params[MODEL1_PARAM].getValue())) { | |||
| if (patch.engine >= 8) { | |||
| patch.engine -= 8; | |||
| } | |||
| @@ -112,7 +129,7 @@ struct Plaits : Module { | |||
| patch.engine = (patch.engine + 1) % 8; | |||
| } | |||
| } | |||
| if (model2Trigger.process(params[MODEL2_PARAM].value)) { | |||
| if (model2Trigger.process(params[MODEL2_PARAM].getValue())) { | |||
| if (patch.engine < 8) { | |||
| patch.engine += 8; | |||
| } | |||
| @@ -123,7 +140,7 @@ struct Plaits : Module { | |||
| // Model lights | |||
| int activeEngine = voice.active_engine(); | |||
| triPhase += 2.f * engineGetSampleTime() * blockSize; | |||
| triPhase += 2.f * args.sampleTime * blockSize; | |||
| if (triPhase >= 1.f) | |||
| triPhase -= 1.f; | |||
| float tri = (triPhase < 0.5f) ? triPhase * 2.f : (1.f - triPhase) * 2.f; | |||
| @@ -134,47 +151,47 @@ struct Plaits : Module { | |||
| } | |||
| // Calculate pitch for lowCpu mode if needed | |||
| float pitch = params[FREQ_PARAM].value; | |||
| float pitch = params[FREQ_PARAM].getValue(); | |||
| if (lowCpu) | |||
| pitch += log2f(48000.f * engineGetSampleTime()); | |||
| pitch += log2f(48000.f * args.sampleTime); | |||
| // Update patch | |||
| patch.note = 60.f + pitch * 12.f; | |||
| patch.harmonics = params[HARMONICS_PARAM].value; | |||
| patch.harmonics = params[HARMONICS_PARAM].getValue(); | |||
| if (!lpg) { | |||
| patch.timbre = params[TIMBRE_PARAM].value; | |||
| patch.morph = params[MORPH_PARAM].value; | |||
| patch.timbre = params[TIMBRE_PARAM].getValue(); | |||
| patch.morph = params[MORPH_PARAM].getValue(); | |||
| } | |||
| else { | |||
| patch.lpg_colour = params[TIMBRE_PARAM].value; | |||
| patch.decay = params[MORPH_PARAM].value; | |||
| patch.lpg_colour = params[TIMBRE_PARAM].getValue(); | |||
| patch.decay = params[MORPH_PARAM].getValue(); | |||
| } | |||
| patch.frequency_modulation_amount = params[FREQ_CV_PARAM].value; | |||
| patch.timbre_modulation_amount = params[TIMBRE_CV_PARAM].value; | |||
| patch.morph_modulation_amount = params[MORPH_CV_PARAM].value; | |||
| patch.frequency_modulation_amount = params[FREQ_CV_PARAM].getValue(); | |||
| patch.timbre_modulation_amount = params[TIMBRE_CV_PARAM].getValue(); | |||
| patch.morph_modulation_amount = params[MORPH_CV_PARAM].getValue(); | |||
| // Update modulations | |||
| modulations.engine = inputs[ENGINE_INPUT].value / 5.f; | |||
| modulations.note = inputs[NOTE_INPUT].value * 12.f; | |||
| modulations.frequency = inputs[FREQ_INPUT].value * 6.f; | |||
| modulations.harmonics = inputs[HARMONICS_INPUT].value / 5.f; | |||
| modulations.timbre = inputs[TIMBRE_INPUT].value / 8.f; | |||
| modulations.morph = inputs[MORPH_INPUT].value / 8.f; | |||
| modulations.engine = inputs[ENGINE_INPUT].getVoltage() / 5.f; | |||
| modulations.note = inputs[NOTE_INPUT].getVoltage() * 12.f; | |||
| modulations.frequency = inputs[FREQ_INPUT].getVoltage() * 6.f; | |||
| modulations.harmonics = inputs[HARMONICS_INPUT].getVoltage() / 5.f; | |||
| modulations.timbre = inputs[TIMBRE_INPUT].getVoltage() / 8.f; | |||
| modulations.morph = inputs[MORPH_INPUT].getVoltage() / 8.f; | |||
| // Triggers at around 0.7 V | |||
| modulations.trigger = inputs[TRIGGER_INPUT].value / 3.f; | |||
| modulations.level = inputs[LEVEL_INPUT].value / 8.f; | |||
| modulations.trigger = inputs[TRIGGER_INPUT].getVoltage() / 3.f; | |||
| modulations.level = inputs[LEVEL_INPUT].getVoltage() / 8.f; | |||
| modulations.frequency_patched = inputs[FREQ_INPUT].active; | |||
| modulations.timbre_patched = inputs[TIMBRE_INPUT].active; | |||
| modulations.morph_patched = inputs[MORPH_INPUT].active; | |||
| modulations.trigger_patched = inputs[TRIGGER_INPUT].active; | |||
| modulations.level_patched = inputs[LEVEL_INPUT].active; | |||
| modulations.frequency_patched = inputs[FREQ_INPUT].isConnected(); | |||
| modulations.timbre_patched = inputs[TIMBRE_INPUT].isConnected(); | |||
| modulations.morph_patched = inputs[MORPH_INPUT].isConnected(); | |||
| modulations.trigger_patched = inputs[TRIGGER_INPUT].isConnected(); | |||
| modulations.level_patched = inputs[LEVEL_INPUT].isConnected(); | |||
| // Render frames | |||
| plaits::Voice::Frame output[blockSize]; | |||
| voice.Render(patch, modulations, output, blockSize); | |||
| // Convert output to frames | |||
| Frame<2> outputFrames[blockSize]; | |||
| dsp::Frame<2> outputFrames[blockSize]; | |||
| for (int i = 0; i < blockSize; i++) { | |||
| outputFrames[i].samples[0] = output[i].out / 32768.f; | |||
| outputFrames[i].samples[1] = output[i].aux / 32768.f; | |||
| @@ -182,12 +199,12 @@ struct Plaits : Module { | |||
| // Convert output | |||
| if (lowCpu) { | |||
| int len = min(outputBuffer.capacity(), blockSize); | |||
| memcpy(outputBuffer.endData(), outputFrames, len * sizeof(Frame<2>)); | |||
| int len = std::min((int) outputBuffer.capacity(), blockSize); | |||
| memcpy(outputBuffer.endData(), outputFrames, len * sizeof(dsp::Frame<2>)); | |||
| outputBuffer.endIncr(len); | |||
| } | |||
| else { | |||
| outputSrc.setRates(48000, engineGetSampleRate()); | |||
| outputSrc.setRates(48000, args.sampleRate); | |||
| int inLen = blockSize; | |||
| int outLen = outputBuffer.capacity(); | |||
| outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | |||
| @@ -197,10 +214,10 @@ struct Plaits : Module { | |||
| // Set output | |||
| if (!outputBuffer.empty()) { | |||
| Frame<2> outputFrame = outputBuffer.shift(); | |||
| dsp::Frame<2> outputFrame = outputBuffer.shift(); | |||
| // Inverting op-amp on outputs | |||
| outputs[OUT_OUTPUT].value = -outputFrame.samples[0] * 5.f; | |||
| outputs[AUX_OUTPUT].value = -outputFrame.samples[1] * 5.f; | |||
| outputs[OUT_OUTPUT].setVoltage(-outputFrame.samples[0] * 5.f); | |||
| outputs[AUX_OUTPUT].setVoltage(-outputFrame.samples[1] * 5.f); | |||
| } | |||
| } | |||
| }; | |||
| @@ -227,35 +244,36 @@ static const std::string modelLabels[16] = { | |||
| struct PlaitsWidget : ModuleWidget { | |||
| PlaitsWidget(Plaits *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Plaits.svg"))); | |||
| PlaitsWidget(Plaits *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Plaits.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addParam(createParam<TL1105>(mm2px(Vec(23.32685, 14.6539)), module, Plaits::MODEL1_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(32.22764, 14.6539)), module, Plaits::MODEL2_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan3PSWhite>(mm2px(Vec(3.1577, 20.21088)), module, Plaits::FREQ_PARAM, -4.0, 4.0, 0.0)); | |||
| addParam(createParam<Rogan3PSWhite>(mm2px(Vec(39.3327, 20.21088)), module, Plaits::HARMONICS_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(mm2px(Vec(4.04171, 49.6562)), module, Plaits::TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(mm2px(Vec(42.71716, 49.6562)), module, Plaits::MORPH_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(7.88712, 77.60705)), module, Plaits::TIMBRE_CV_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(27.2245, 77.60705)), module, Plaits::FREQ_CV_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(46.56189, 77.60705)), module, Plaits::MORPH_CV_PARAM, -1.0, 1.0, 0.0)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(3.31381, 92.48067)), PortWidget::INPUT, module, Plaits::ENGINE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(14.75983, 92.48067)), PortWidget::INPUT, module, Plaits::TIMBRE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(26.20655, 92.48067)), PortWidget::INPUT, module, Plaits::FREQ_INPUT)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(37.65257, 92.48067)), PortWidget::INPUT, module, Plaits::MORPH_INPUT)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(49.0986, 92.48067)), PortWidget::INPUT, module, Plaits::HARMONICS_INPUT)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(3.31381, 107.08103)), PortWidget::INPUT, module, Plaits::TRIGGER_INPUT)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(14.75983, 107.08103)), PortWidget::INPUT, module, Plaits::LEVEL_INPUT)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(26.20655, 107.08103)), PortWidget::INPUT, module, Plaits::NOTE_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(mm2px(Vec(37.65257, 107.08103)), PortWidget::OUTPUT, module, Plaits::OUT_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(mm2px(Vec(49.0986, 107.08103)), PortWidget::OUTPUT, module, Plaits::AUX_OUTPUT)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(23.32685, 14.6539)), module, Plaits::MODEL1_PARAM)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(32.22764, 14.6539)), module, Plaits::MODEL2_PARAM)); | |||
| addParam(createParam<Rogan3PSWhite>(mm2px(Vec(3.1577, 20.21088)), module, Plaits::FREQ_PARAM)); | |||
| addParam(createParam<Rogan3PSWhite>(mm2px(Vec(39.3327, 20.21088)), module, Plaits::HARMONICS_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(mm2px(Vec(4.04171, 49.6562)), module, Plaits::TIMBRE_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(mm2px(Vec(42.71716, 49.6562)), module, Plaits::MORPH_PARAM)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(7.88712, 77.60705)), module, Plaits::TIMBRE_CV_PARAM)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(27.2245, 77.60705)), module, Plaits::FREQ_CV_PARAM)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(46.56189, 77.60705)), module, Plaits::MORPH_CV_PARAM)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(3.31381, 92.48067)), module, Plaits::ENGINE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(14.75983, 92.48067)), module, Plaits::TIMBRE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(26.20655, 92.48067)), module, Plaits::FREQ_INPUT)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(37.65257, 92.48067)), module, Plaits::MORPH_INPUT)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(49.0986, 92.48067)), module, Plaits::HARMONICS_INPUT)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(3.31381, 107.08103)), module, Plaits::TRIGGER_INPUT)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(14.75983, 107.08103)), module, Plaits::LEVEL_INPUT)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(26.20655, 107.08103)), module, Plaits::NOTE_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(mm2px(Vec(37.65257, 107.08103)), module, Plaits::OUT_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(mm2px(Vec(49.0986, 107.08103)), module, Plaits::AUX_OUTPUT)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(28.79498, 23.31649)), module, Plaits::MODEL_LIGHT + 0 * 2)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(28.79498, 28.71704)), module, Plaits::MODEL_LIGHT + 1 * 2)); | |||
| @@ -45,10 +45,10 @@ struct Rings : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| SampleRateConverter<1> inputSrc; | |||
| SampleRateConverter<2> outputSrc; | |||
| DoubleRingBuffer<Frame<1>, 256> inputBuffer; | |||
| DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||
| dsp::SampleRateConverter<1> inputSrc; | |||
| dsp::SampleRateConverter<2> outputSrc; | |||
| dsp::DoubleRingBuffer<dsp::Frame<1>, 256> inputBuffer; | |||
| dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||
| uint16_t reverb_buffer[32768] = {}; | |||
| rings::Part part; | |||
| @@ -57,14 +57,14 @@ struct Rings : Module { | |||
| bool strum = false; | |||
| bool lastStrum = false; | |||
| SchmittTrigger polyphonyTrigger; | |||
| SchmittTrigger modelTrigger; | |||
| dsp::SchmittTrigger polyphonyTrigger; | |||
| dsp::SchmittTrigger modelTrigger; | |||
| int polyphonyMode = 0; | |||
| rings::ResonatorModel resonatorModel = rings::RESONATOR_MODEL_MODAL; | |||
| bool easterEgg = false; | |||
| Rings(); | |||
| void step() override; | |||
| void process(const ProcessArgs &args) override; | |||
| json_t *dataToJson() override { | |||
| json_t *rootJ = json_object(); | |||
| @@ -99,13 +99,27 @@ struct Rings : Module { | |||
| } | |||
| void onRandomize() override { | |||
| polyphonyMode = randomu32() % 3; | |||
| resonatorModel = (rings::ResonatorModel) (randomu32() % 3); | |||
| polyphonyMode = random::u32() % 3; | |||
| resonatorModel = (rings::ResonatorModel) (random::u32() % 3); | |||
| } | |||
| }; | |||
| Rings::Rings() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Rings::Rings() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Rings::POLYPHONY_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Rings::RESONATOR_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Rings::FREQUENCY_PARAM, 0.0, 60.0, 30.0); | |||
| configParam(Rings::STRUCTURE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Rings::BRIGHTNESS_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Rings::DAMPING_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Rings::POSITION_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Rings::BRIGHTNESS_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Rings::FREQUENCY_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Rings::DAMPING_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Rings::STRUCTURE_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Rings::POSITION_MOD_PARAM, -1.0, 1.0, 0.0); | |||
| memset(&strummer, 0, sizeof(strummer)); | |||
| memset(&part, 0, sizeof(part)); | |||
| memset(&string_synth, 0, sizeof(string_synth)); | |||
| @@ -115,28 +129,28 @@ Rings::Rings() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| string_synth.Init(reverb_buffer); | |||
| } | |||
| void Rings::step() { | |||
| void Rings::process(const ProcessArgs &args) { | |||
| // TODO | |||
| // "Normalized to a pulse/burst generator that reacts to note changes on the V/OCT input." | |||
| // Get input | |||
| if (!inputBuffer.full()) { | |||
| Frame<1> f; | |||
| f.samples[0] = inputs[IN_INPUT].value / 5.0; | |||
| dsp::Frame<1> f; | |||
| f.samples[0] = inputs[IN_INPUT].getVoltage() / 5.0; | |||
| inputBuffer.push(f); | |||
| } | |||
| if (!strum) { | |||
| strum = inputs[STRUM_INPUT].value >= 1.0; | |||
| strum = inputs[STRUM_INPUT].getVoltage() >= 1.0; | |||
| } | |||
| // Polyphony / model | |||
| if (polyphonyTrigger.process(params[POLYPHONY_PARAM].value)) { | |||
| if (polyphonyTrigger.process(params[POLYPHONY_PARAM].getValue())) { | |||
| polyphonyMode = (polyphonyMode + 1) % 3; | |||
| } | |||
| lights[POLYPHONY_GREEN_LIGHT].value = (polyphonyMode == 0 || polyphonyMode == 1) ? 1.0 : 0.0; | |||
| lights[POLYPHONY_RED_LIGHT].value = (polyphonyMode == 1 || polyphonyMode == 2) ? 1.0 : 0.0; | |||
| if (modelTrigger.process(params[RESONATOR_PARAM].value)) { | |||
| if (modelTrigger.process(params[RESONATOR_PARAM].getValue())) { | |||
| resonatorModel = (rings::ResonatorModel) ((resonatorModel + 1) % 3); | |||
| } | |||
| int modelColor = resonatorModel % 3; | |||
| @@ -148,10 +162,10 @@ void Rings::step() { | |||
| float in[24] = {}; | |||
| // Convert input buffer | |||
| { | |||
| inputSrc.setRates(engineGetSampleRate(), 48000); | |||
| inputSrc.setRates(args.sampleRate, 48000); | |||
| int inLen = inputBuffer.size(); | |||
| int outLen = 24; | |||
| inputSrc.process(inputBuffer.startData(), &inLen, (Frame<1>*) in, &outLen); | |||
| inputSrc.process(inputBuffer.startData(), &inLen, (dsp::Frame<1>*) in, &outLen); | |||
| inputBuffer.startIncr(inLen); | |||
| } | |||
| @@ -167,26 +181,26 @@ void Rings::step() { | |||
| // Patch | |||
| rings::Patch patch; | |||
| float structure = params[STRUCTURE_PARAM].value + 3.3*quadraticBipolar(params[STRUCTURE_MOD_PARAM].value)*inputs[STRUCTURE_MOD_INPUT].value/5.0; | |||
| float structure = params[STRUCTURE_PARAM].getValue() + 3.3*dsp::quadraticBipolar(params[STRUCTURE_MOD_PARAM].getValue())*inputs[STRUCTURE_MOD_INPUT].getVoltage()/5.0; | |||
| patch.structure = clamp(structure, 0.0f, 0.9995f); | |||
| patch.brightness = clamp(params[BRIGHTNESS_PARAM].value + 3.3*quadraticBipolar(params[BRIGHTNESS_MOD_PARAM].value)*inputs[BRIGHTNESS_MOD_INPUT].value/5.0, 0.0f, 1.0f); | |||
| patch.damping = clamp(params[DAMPING_PARAM].value + 3.3*quadraticBipolar(params[DAMPING_MOD_PARAM].value)*inputs[DAMPING_MOD_INPUT].value/5.0, 0.0f, 0.9995f); | |||
| patch.position = clamp(params[POSITION_PARAM].value + 3.3*quadraticBipolar(params[POSITION_MOD_PARAM].value)*inputs[POSITION_MOD_INPUT].value/5.0, 0.0f, 0.9995f); | |||
| patch.brightness = clamp(params[BRIGHTNESS_PARAM].getValue() + 3.3*dsp::quadraticBipolar(params[BRIGHTNESS_MOD_PARAM].getValue())*inputs[BRIGHTNESS_MOD_INPUT].getVoltage()/5.0, 0.0f, 1.0f); | |||
| patch.damping = clamp(params[DAMPING_PARAM].getValue() + 3.3*dsp::quadraticBipolar(params[DAMPING_MOD_PARAM].getValue())*inputs[DAMPING_MOD_INPUT].getVoltage()/5.0, 0.0f, 0.9995f); | |||
| patch.position = clamp(params[POSITION_PARAM].getValue() + 3.3*dsp::quadraticBipolar(params[POSITION_MOD_PARAM].getValue())*inputs[POSITION_MOD_INPUT].getVoltage()/5.0, 0.0f, 0.9995f); | |||
| // Performance | |||
| rings::PerformanceState performance_state; | |||
| performance_state.note = 12.0*inputs[PITCH_INPUT].normalize(1/12.0); | |||
| float transpose = params[FREQUENCY_PARAM].value; | |||
| performance_state.note = 12.0*inputs[PITCH_INPUT].getNormalVoltage(1/12.0); | |||
| float transpose = params[FREQUENCY_PARAM].getValue(); | |||
| // Quantize transpose if pitch input is connected | |||
| if (inputs[PITCH_INPUT].active) { | |||
| if (inputs[PITCH_INPUT].isConnected()) { | |||
| transpose = roundf(transpose); | |||
| } | |||
| performance_state.tonic = 12.0 + clamp(transpose, 0.0f, 60.0f); | |||
| performance_state.fm = clamp(48.0 * 3.3*quarticBipolar(params[FREQUENCY_MOD_PARAM].value) * inputs[FREQUENCY_MOD_INPUT].normalize(1.0)/5.0, -48.0f, 48.0f); | |||
| performance_state.fm = clamp(48.0 * 3.3*dsp::quarticBipolar(params[FREQUENCY_MOD_PARAM].getValue()) * inputs[FREQUENCY_MOD_INPUT].getNormalVoltage(1.0)/5.0, -48.0f, 48.0f); | |||
| performance_state.internal_exciter = !inputs[IN_INPUT].active; | |||
| performance_state.internal_strum = !inputs[STRUM_INPUT].active; | |||
| performance_state.internal_note = !inputs[PITCH_INPUT].active; | |||
| performance_state.internal_exciter = !inputs[IN_INPUT].isConnected(); | |||
| performance_state.internal_strum = !inputs[STRUM_INPUT].isConnected(); | |||
| performance_state.internal_note = !inputs[PITCH_INPUT].isConnected(); | |||
| // TODO | |||
| // "Normalized to a step detector on the V/OCT input and a transient detector on the IN input." | |||
| @@ -210,13 +224,13 @@ void Rings::step() { | |||
| // Convert output buffer | |||
| { | |||
| Frame<2> outputFrames[24]; | |||
| dsp::Frame<2> outputFrames[24]; | |||
| for (int i = 0; i < 24; i++) { | |||
| outputFrames[i].samples[0] = out[i]; | |||
| outputFrames[i].samples[1] = aux[i]; | |||
| } | |||
| outputSrc.setRates(48000, engineGetSampleRate()); | |||
| outputSrc.setRates(48000, args.sampleRate); | |||
| int inLen = 24; | |||
| int outLen = outputBuffer.capacity(); | |||
| outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | |||
| @@ -226,57 +240,58 @@ void Rings::step() { | |||
| // Set output | |||
| if (!outputBuffer.empty()) { | |||
| Frame<2> outputFrame = outputBuffer.shift(); | |||
| dsp::Frame<2> outputFrame = outputBuffer.shift(); | |||
| // "Note that you need to insert a jack into each output to split the signals: when only one jack is inserted, both signals are mixed together." | |||
| if (outputs[ODD_OUTPUT].active && outputs[EVEN_OUTPUT].active) { | |||
| outputs[ODD_OUTPUT].value = clamp(outputFrame.samples[0], -1.0, 1.0)*5.0; | |||
| outputs[EVEN_OUTPUT].value = clamp(outputFrame.samples[1], -1.0, 1.0)*5.0; | |||
| if (outputs[ODD_OUTPUT].isConnected() && outputs[EVEN_OUTPUT].isConnected()) { | |||
| outputs[ODD_OUTPUT].setVoltage(clamp(outputFrame.samples[0], -1.0, 1.0)*5.0); | |||
| outputs[EVEN_OUTPUT].setVoltage(clamp(outputFrame.samples[1], -1.0, 1.0)*5.0); | |||
| } | |||
| else { | |||
| float v = clamp(outputFrame.samples[0] + outputFrame.samples[1], -1.0, 1.0)*5.0; | |||
| outputs[ODD_OUTPUT].value = v; | |||
| outputs[EVEN_OUTPUT].value = v; | |||
| outputs[ODD_OUTPUT].setVoltage(v); | |||
| outputs[EVEN_OUTPUT].setVoltage(v); | |||
| } | |||
| } | |||
| } | |||
| struct RingsWidget : ModuleWidget { | |||
| RingsWidget(Rings *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Rings.svg"))); | |||
| RingsWidget(Rings *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Rings.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(180, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(180, 365))); | |||
| addParam(createParam<TL1105>(Vec(14, 40), module, Rings::POLYPHONY_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(Vec(179, 40), module, Rings::RESONATOR_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(29, 72), module, Rings::FREQUENCY_PARAM, 0.0, 60.0, 30.0)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(126, 72), module, Rings::STRUCTURE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(13, 158), module, Rings::BRIGHTNESS_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(83, 158), module, Rings::DAMPING_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(154, 158), module, Rings::POSITION_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Trimpot>(Vec(19, 229), module, Rings::BRIGHTNESS_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(57, 229), module, Rings::FREQUENCY_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(96, 229), module, Rings::DAMPING_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(134, 229), module, Rings::STRUCTURE_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(173, 229), module, Rings::POSITION_MOD_PARAM, -1.0, 1.0, 0.0)); | |||
| addInput(createPort<PJ301MPort>(Vec(15, 273), PortWidget::INPUT, module, Rings::BRIGHTNESS_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(54, 273), PortWidget::INPUT, module, Rings::FREQUENCY_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(92, 273), PortWidget::INPUT, module, Rings::DAMPING_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(131, 273), PortWidget::INPUT, module, Rings::STRUCTURE_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(169, 273), PortWidget::INPUT, module, Rings::POSITION_MOD_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(15, 316), PortWidget::INPUT, module, Rings::STRUM_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(54, 316), PortWidget::INPUT, module, Rings::PITCH_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(92, 316), PortWidget::INPUT, module, Rings::IN_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(131, 316), PortWidget::OUTPUT, module, Rings::ODD_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(169, 316), PortWidget::OUTPUT, module, Rings::EVEN_OUTPUT)); | |||
| addParam(createParam<TL1105>(Vec(14, 40), module, Rings::POLYPHONY_PARAM)); | |||
| addParam(createParam<TL1105>(Vec(179, 40), module, Rings::RESONATOR_PARAM)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(29, 72), module, Rings::FREQUENCY_PARAM)); | |||
| addParam(createParam<Rogan3PSWhite>(Vec(126, 72), module, Rings::STRUCTURE_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(13, 158), module, Rings::BRIGHTNESS_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(83, 158), module, Rings::DAMPING_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(154, 158), module, Rings::POSITION_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(19, 229), module, Rings::BRIGHTNESS_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(57, 229), module, Rings::FREQUENCY_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(96, 229), module, Rings::DAMPING_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(134, 229), module, Rings::STRUCTURE_MOD_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(173, 229), module, Rings::POSITION_MOD_PARAM)); | |||
| addInput(createInput<PJ301MPort>(Vec(15, 273), module, Rings::BRIGHTNESS_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(54, 273), module, Rings::FREQUENCY_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(92, 273), module, Rings::DAMPING_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(131, 273), module, Rings::STRUCTURE_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(169, 273), module, Rings::POSITION_MOD_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(15, 316), module, Rings::STRUM_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(54, 316), module, Rings::PITCH_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(92, 316), module, Rings::IN_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(131, 316), module, Rings::ODD_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(169, 316), module, Rings::EVEN_OUTPUT)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(Vec(37, 43), module, Rings::POLYPHONY_GREEN_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(Vec(162, 43), module, Rings::RESONATOR_GREEN_LIGHT)); | |||
| @@ -30,29 +30,37 @@ struct Shades : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| Shades() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||
| void step() override; | |||
| Shades() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Shades::GAIN1_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Shades::GAIN2_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Shades::GAIN3_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Shades::MODE1_PARAM, 0.0, 1.0, 1.0); | |||
| configParam(Shades::MODE2_PARAM, 0.0, 1.0, 1.0); | |||
| configParam(Shades::MODE3_PARAM, 0.0, 1.0, 1.0); | |||
| } | |||
| void process(const ProcessArgs &args) override; | |||
| }; | |||
| void Shades::step() { | |||
| void Shades::process(const ProcessArgs &args) { | |||
| float out = 0.0; | |||
| for (int i = 0; i < 3; i++) { | |||
| float in = inputs[IN1_INPUT + i].normalize(5.0); | |||
| if ((int)params[MODE1_PARAM + i].value == 1) { | |||
| if ((int)params[MODE1_PARAM + i].getValue() == 1) { | |||
| // attenuverter | |||
| in *= 2.0 * params[GAIN1_PARAM + i].value - 1.0; | |||
| in *= 2.0 * params[GAIN1_PARAM + i].getValue() - 1.0; | |||
| } | |||
| else { | |||
| // attenuator | |||
| in *= params[GAIN1_PARAM + i].value; | |||
| in *= params[GAIN1_PARAM + i].getValue(); | |||
| } | |||
| out += in; | |||
| lights[OUT1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, out / 5.0)); | |||
| lights[OUT1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -out / 5.0)); | |||
| if (outputs[OUT1_OUTPUT + i].active) { | |||
| outputs[OUT1_OUTPUT + i].value = out; | |||
| if (outputs[OUT1_OUTPUT + i].isConnected()) { | |||
| outputs[OUT1_OUTPUT + i].setVoltage(out); | |||
| out = 0.0; | |||
| } | |||
| } | |||
| @@ -60,27 +68,28 @@ void Shades::step() { | |||
| struct ShadesWidget : ModuleWidget { | |||
| ShadesWidget(Shades *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Shades.svg"))); | |||
| ShadesWidget(Shades *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Shades.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addParam(createParam<Rogan1PSRed>(Vec(40, 40), module, Shades::GAIN1_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(40, 106), module, Shades::GAIN2_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(40, 172), module, Shades::GAIN3_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Rogan1PSRed>(Vec(40, 40), module, Shades::GAIN1_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(40, 106), module, Shades::GAIN2_PARAM)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(40, 172), module, Shades::GAIN3_PARAM)); | |||
| addParam(createParam<CKSS>(Vec(10, 51), module, Shades::MODE1_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<CKSS>(Vec(10, 117), module, Shades::MODE2_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<CKSS>(Vec(10, 183), module, Shades::MODE3_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<CKSS>(Vec(10, 51), module, Shades::MODE1_PARAM)); | |||
| addParam(createParam<CKSS>(Vec(10, 117), module, Shades::MODE2_PARAM)); | |||
| addParam(createParam<CKSS>(Vec(10, 183), module, Shades::MODE3_PARAM)); | |||
| addInput(createPort<PJ301MPort>(Vec(9, 245), PortWidget::INPUT, module, Shades::IN1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(9, 281), PortWidget::INPUT, module, Shades::IN2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(9, 317), PortWidget::INPUT, module, Shades::IN3_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(9, 245), module, Shades::IN1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(9, 281), module, Shades::IN2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(9, 317), module, Shades::IN3_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(56, 245), PortWidget::OUTPUT, module, Shades::OUT1_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(56, 281), PortWidget::OUTPUT, module, Shades::OUT2_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(56, 317), PortWidget::OUTPUT, module, Shades::OUT3_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(56, 245), module, Shades::OUT1_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(56, 281), module, Shades::OUT2_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(56, 317), module, Shades::OUT3_OUTPUT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(41, 254), module, Shades::OUT1_POS_LIGHT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(41, 290), module, Shades::OUT2_POS_LIGHT)); | |||
| @@ -15,14 +15,14 @@ struct LongPressButton { | |||
| }; | |||
| float pressedTime = 0.f; | |||
| BooleanTrigger trigger; | |||
| dsp::BooleanTrigger trigger; | |||
| Events step(Param ¶m) { | |||
| Events result = NO_PRESS; | |||
| bool pressed = param.value > 0.f; | |||
| if (pressed && pressedTime >= 0.f) { | |||
| pressedTime += engineGetSampleTime(); | |||
| pressedTime += APP->engine->getSampleTime(); | |||
| if (pressedTime >= 1.f) { | |||
| pressedTime = -1.f; | |||
| result = LONG_PRESS; | |||
| @@ -153,7 +153,27 @@ struct Stages : Module { | |||
| int blockIndex = 0; | |||
| GroupBuilder groupBuilder; | |||
| Stages() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Stages() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Stages::SHAPE_PARAMS + 0, 0.0, 1.0, 0.5); | |||
| configParam(Stages::SHAPE_PARAMS + 1, 0.0, 1.0, 0.5); | |||
| configParam(Stages::SHAPE_PARAMS + 2, 0.0, 1.0, 0.5); | |||
| configParam(Stages::SHAPE_PARAMS + 3, 0.0, 1.0, 0.5); | |||
| configParam(Stages::SHAPE_PARAMS + 4, 0.0, 1.0, 0.5); | |||
| configParam(Stages::SHAPE_PARAMS + 5, 0.0, 1.0, 0.5); | |||
| configParam(Stages::TYPE_PARAMS + 0, 0.0, 1.0, 0.0); | |||
| configParam(Stages::TYPE_PARAMS + 1, 0.0, 1.0, 0.0); | |||
| configParam(Stages::TYPE_PARAMS + 2, 0.0, 1.0, 0.0); | |||
| configParam(Stages::TYPE_PARAMS + 3, 0.0, 1.0, 0.0); | |||
| configParam(Stages::TYPE_PARAMS + 4, 0.0, 1.0, 0.0); | |||
| configParam(Stages::TYPE_PARAMS + 5, 0.0, 1.0, 0.0); | |||
| configParam(Stages::LEVEL_PARAMS + 0, 0.0, 1.0, 0.5); | |||
| configParam(Stages::LEVEL_PARAMS + 1, 0.0, 1.0, 0.5); | |||
| configParam(Stages::LEVEL_PARAMS + 2, 0.0, 1.0, 0.5); | |||
| configParam(Stages::LEVEL_PARAMS + 3, 0.0, 1.0, 0.5); | |||
| configParam(Stages::LEVEL_PARAMS + 4, 0.0, 1.0, 0.5); | |||
| configParam(Stages::LEVEL_PARAMS + 5, 0.0, 1.0, 0.5); | |||
| onReset(); | |||
| } | |||
| @@ -203,7 +223,7 @@ struct Stages : Module { | |||
| void onSampleRateChange() override { | |||
| for (int i = 0; i < NUM_CHANNELS; i++) { | |||
| segment_generator[i].SetSampleRate(engineGetSampleRate()); | |||
| segment_generator[i].SetSampleRate(APP->engine->getSampleRate()); | |||
| } | |||
| } | |||
| @@ -212,8 +232,8 @@ struct Stages : Module { | |||
| float primaries[NUM_CHANNELS]; | |||
| float secondaries[NUM_CHANNELS]; | |||
| for (int i = 0; i < NUM_CHANNELS; i++) { | |||
| primaries[i] = clamp(params[LEVEL_PARAMS + i].value + inputs[LEVEL_INPUTS + i].value / 8.f, 0.f, 1.f); | |||
| secondaries[i] = params[SHAPE_PARAMS + i].value; | |||
| primaries[i] = clamp(params[LEVEL_PARAMS + i].getValue() + inputs[LEVEL_INPUTS + i].getVoltage() / 8.f, 0.f, 1.f); | |||
| secondaries[i] = params[SHAPE_PARAMS + i].getValue(); | |||
| } | |||
| // See if the group associations have changed since the last group | |||
| @@ -309,9 +329,9 @@ struct Stages : Module { | |||
| } | |||
| } | |||
| void step() override { | |||
| void process(const ProcessArgs &args) override { | |||
| // Oscillate flashing the type lights | |||
| lightOscillatorPhase += 0.5f * engineGetSampleTime(); | |||
| lightOscillatorPhase += 0.5f * args.sampleTime; | |||
| if (lightOscillatorPhase >= 1.0f) | |||
| lightOscillatorPhase -= 1.0f; | |||
| @@ -327,7 +347,7 @@ struct Stages : Module { | |||
| // Input | |||
| for (int i = 0; i < NUM_CHANNELS; i++) { | |||
| bool gate = (inputs[GATE_INPUTS + i].value >= 1.7f); | |||
| bool gate = (inputs[GATE_INPUTS + i].getVoltage() >= 1.7f); | |||
| last_gate_flags[i] = stmlib::ExtractGateFlags(last_gate_flags[i], gate); | |||
| gate_flags[i][blockIndex] = last_gate_flags[i]; | |||
| } | |||
| @@ -347,8 +367,8 @@ struct Stages : Module { | |||
| int segment = group.first_segment + j; | |||
| float envelope = envelopeBuffer[segment][blockIndex]; | |||
| outputs[ENVELOPE_OUTPUTS + segment].value = envelope * 8.f; | |||
| lights[ENVELOPE_LIGHTS + segment].setBrightnessSmooth(envelope); | |||
| outputs[ENVELOPE_OUTPUTS + segment].setVoltage(envelope * 8.f); | |||
| lights[ENVELOPE_LIGHTS + segment].setSmoothBrightness(envelope, args.sampleTime); | |||
| numberOfLoopsInGroup += configurations[segment].loop ? 1 : 0; | |||
| float flashlevel = 1.f; | |||
| @@ -373,52 +393,53 @@ struct Stages : Module { | |||
| struct StagesWidget : ModuleWidget { | |||
| StagesWidget(Stages *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Stages.svg"))); | |||
| StagesWidget(Stages *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Stages.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(3.72965, 13.98158)), module, Stages::SHAPE_PARAMS + 0, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(15.17012, 13.98158)), module, Stages::SHAPE_PARAMS + 1, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(26.6099, 13.98158)), module, Stages::SHAPE_PARAMS + 2, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(38.07174, 13.98158)), module, Stages::SHAPE_PARAMS + 3, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(49.51152, 13.98158)), module, Stages::SHAPE_PARAMS + 4, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(60.95199, 13.98158)), module, Stages::SHAPE_PARAMS + 5, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(4.17259, 32.37248)), module, Stages::TYPE_PARAMS + 0, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(15.61237, 32.37248)), module, Stages::TYPE_PARAMS + 1, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(27.05284, 32.37248)), module, Stages::TYPE_PARAMS + 2, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(38.51399, 32.37248)), module, Stages::TYPE_PARAMS + 3, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(49.95446, 32.37248)), module, Stages::TYPE_PARAMS + 4, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(61.39424, 32.37248)), module, Stages::TYPE_PARAMS + 5, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(3.36193, 43.06508)), module, Stages::LEVEL_PARAMS + 0, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(14.81619, 43.06508)), module, Stages::LEVEL_PARAMS + 1, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(26.26975, 43.06508)), module, Stages::LEVEL_PARAMS + 2, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(37.70265, 43.06508)), module, Stages::LEVEL_PARAMS + 3, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(49.15759, 43.06508)), module, Stages::LEVEL_PARAMS + 4, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(60.61184, 43.06508)), module, Stages::LEVEL_PARAMS + 5, 0.0, 1.0, 0.5)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(2.70756, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 0)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(14.14734, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 1)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(25.58781, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 2)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(37.04896, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 3)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(48.48943, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 4)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(59.92921, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 5)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(2.70756, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 0)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(14.14734, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 1)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(25.58781, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 2)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(37.04896, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 3)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(48.48943, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 4)); | |||
| addInput(createPort<PJ301MPort>(mm2px(Vec(59.92921, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 5)); | |||
| addOutput(createPort<PJ301MPort>(mm2px(Vec(2.70756, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 0)); | |||
| addOutput(createPort<PJ301MPort>(mm2px(Vec(14.14734, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 1)); | |||
| addOutput(createPort<PJ301MPort>(mm2px(Vec(25.58781, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 2)); | |||
| addOutput(createPort<PJ301MPort>(mm2px(Vec(37.04896, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 3)); | |||
| addOutput(createPort<PJ301MPort>(mm2px(Vec(48.48943, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 4)); | |||
| addOutput(createPort<PJ301MPort>(mm2px(Vec(59.92921, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 5)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(3.72965, 13.98158)), module, Stages::SHAPE_PARAMS + 0)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(15.17012, 13.98158)), module, Stages::SHAPE_PARAMS + 1)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(26.6099, 13.98158)), module, Stages::SHAPE_PARAMS + 2)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(38.07174, 13.98158)), module, Stages::SHAPE_PARAMS + 3)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(49.51152, 13.98158)), module, Stages::SHAPE_PARAMS + 4)); | |||
| addParam(createParam<Trimpot>(mm2px(Vec(60.95199, 13.98158)), module, Stages::SHAPE_PARAMS + 5)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(4.17259, 32.37248)), module, Stages::TYPE_PARAMS + 0)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(15.61237, 32.37248)), module, Stages::TYPE_PARAMS + 1)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(27.05284, 32.37248)), module, Stages::TYPE_PARAMS + 2)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(38.51399, 32.37248)), module, Stages::TYPE_PARAMS + 3)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(49.95446, 32.37248)), module, Stages::TYPE_PARAMS + 4)); | |||
| addParam(createParam<TL1105>(mm2px(Vec(61.39424, 32.37248)), module, Stages::TYPE_PARAMS + 5)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(3.36193, 43.06508)), module, Stages::LEVEL_PARAMS + 0)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(14.81619, 43.06508)), module, Stages::LEVEL_PARAMS + 1)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(26.26975, 43.06508)), module, Stages::LEVEL_PARAMS + 2)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(37.70265, 43.06508)), module, Stages::LEVEL_PARAMS + 3)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(49.15759, 43.06508)), module, Stages::LEVEL_PARAMS + 4)); | |||
| addParam(createParam<LEDSliderGreen>(mm2px(Vec(60.61184, 43.06508)), module, Stages::LEVEL_PARAMS + 5)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(2.70756, 77.75277)), module, Stages::LEVEL_INPUTS + 0)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(14.14734, 77.75277)), module, Stages::LEVEL_INPUTS + 1)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(25.58781, 77.75277)), module, Stages::LEVEL_INPUTS + 2)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(37.04896, 77.75277)), module, Stages::LEVEL_INPUTS + 3)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(48.48943, 77.75277)), module, Stages::LEVEL_INPUTS + 4)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(59.92921, 77.75277)), module, Stages::LEVEL_INPUTS + 5)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(2.70756, 92.35239)), module, Stages::GATE_INPUTS + 0)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(14.14734, 92.35239)), module, Stages::GATE_INPUTS + 1)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(25.58781, 92.35239)), module, Stages::GATE_INPUTS + 2)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(37.04896, 92.35239)), module, Stages::GATE_INPUTS + 3)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(48.48943, 92.35239)), module, Stages::GATE_INPUTS + 4)); | |||
| addInput(createInput<PJ301MPort>(mm2px(Vec(59.92921, 92.35239)), module, Stages::GATE_INPUTS + 5)); | |||
| addOutput(createOutput<PJ301MPort>(mm2px(Vec(2.70756, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 0)); | |||
| addOutput(createOutput<PJ301MPort>(mm2px(Vec(14.14734, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 1)); | |||
| addOutput(createOutput<PJ301MPort>(mm2px(Vec(25.58781, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 2)); | |||
| addOutput(createOutput<PJ301MPort>(mm2px(Vec(37.04896, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 3)); | |||
| addOutput(createOutput<PJ301MPort>(mm2px(Vec(48.48943, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 4)); | |||
| addOutput(createOutput<PJ301MPort>(mm2px(Vec(59.92921, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 5)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(5.27737, 26.74447)), module, Stages::TYPE_LIGHTS + 0 * 2)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(16.73784, 26.74447)), module, Stages::TYPE_LIGHTS + 1 * 2)); | |||
| @@ -47,11 +47,11 @@ struct Tides : Module { | |||
| tides::Generator generator; | |||
| int frame = 0; | |||
| uint8_t lastGate; | |||
| SchmittTrigger modeTrigger; | |||
| SchmittTrigger rangeTrigger; | |||
| dsp::SchmittTrigger modeTrigger; | |||
| dsp::SchmittTrigger rangeTrigger; | |||
| Tides(); | |||
| void step() override; | |||
| void process(const ProcessArgs &args) override; | |||
| void onReset() override { | |||
| @@ -61,8 +61,8 @@ struct Tides : Module { | |||
| } | |||
| void onRandomize() override { | |||
| generator.set_range((tides::GeneratorRange) (randomu32() % 3)); | |||
| generator.set_mode((tides::GeneratorMode) (randomu32() % 3)); | |||
| generator.set_range((tides::GeneratorRange) (random::u32() % 3)); | |||
| generator.set_mode((tides::GeneratorMode) (random::u32() % 3)); | |||
| } | |||
| json_t *dataToJson() override { | |||
| @@ -94,16 +94,25 @@ struct Tides : Module { | |||
| }; | |||
| Tides::Tides() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Tides::Tides() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Tides::MODE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Tides::RANGE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Tides::FREQUENCY_PARAM, -48.0, 48.0, 0.0); | |||
| configParam(Tides::FM_PARAM, -12.0, 12.0, 0.0); | |||
| configParam(Tides::SHAPE_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Tides::SLOPE_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Tides::SMOOTHNESS_PARAM, -1.0, 1.0, 0.0); | |||
| memset(&generator, 0, sizeof(generator)); | |||
| generator.Init(); | |||
| generator.set_sync(false); | |||
| onReset(); | |||
| } | |||
| void Tides::step() { | |||
| void Tides::process(const ProcessArgs &args) { | |||
| tides::GeneratorMode mode = generator.mode(); | |||
| if (modeTrigger.process(params[MODE_PARAM].value)) { | |||
| if (modeTrigger.process(params[MODE_PARAM].getValue())) { | |||
| mode = (tides::GeneratorMode) (((int)mode - 1 + 3) % 3); | |||
| generator.set_mode(mode); | |||
| } | |||
| @@ -111,7 +120,7 @@ void Tides::step() { | |||
| lights[MODE_RED_LIGHT].value = (mode == 0) ? 1.0 : 0.0; | |||
| tides::GeneratorRange range = generator.range(); | |||
| if (rangeTrigger.process(params[RANGE_PARAM].value)) { | |||
| if (rangeTrigger.process(params[RANGE_PARAM].getValue())) { | |||
| range = (tides::GeneratorRange) (((int)range - 1 + 3) % 3); | |||
| generator.set_range(range); | |||
| } | |||
| @@ -123,18 +132,18 @@ void Tides::step() { | |||
| frame = 0; | |||
| // Pitch | |||
| float pitch = params[FREQUENCY_PARAM].value; | |||
| pitch += 12.0 * inputs[PITCH_INPUT].value; | |||
| pitch += params[FM_PARAM].value * inputs[FM_INPUT].normalize(0.1) / 5.0; | |||
| float pitch = params[FREQUENCY_PARAM].getValue(); | |||
| pitch += 12.0 * inputs[PITCH_INPUT].getVoltage(); | |||
| pitch += params[FM_PARAM].getValue() * inputs[FM_INPUT].getNormalVoltage(0.1) / 5.0; | |||
| pitch += 60.0; | |||
| // Scale to the global sample rate | |||
| pitch += log2f(48000.0 / engineGetSampleRate()) * 12.0; | |||
| pitch += log2f(48000.0 / args.sampleRate) * 12.0; | |||
| generator.set_pitch((int) clamp(pitch * 0x80, (float) -0x8000, (float) 0x7fff)); | |||
| // Slope, smoothness, pitch | |||
| int16_t shape = clamp(params[SHAPE_PARAM].value + inputs[SHAPE_INPUT].value / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||
| int16_t slope = clamp(params[SLOPE_PARAM].value + inputs[SLOPE_INPUT].value / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||
| int16_t smoothness = clamp(params[SMOOTHNESS_PARAM].value + inputs[SMOOTHNESS_INPUT].value / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||
| int16_t shape = clamp(params[SHAPE_PARAM].getValue() + inputs[SHAPE_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||
| int16_t slope = clamp(params[SLOPE_PARAM].getValue() + inputs[SLOPE_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||
| int16_t smoothness = clamp(params[SMOOTHNESS_PARAM].getValue() + inputs[SMOOTHNESS_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||
| generator.set_shape(shape); | |||
| generator.set_slope(slope); | |||
| generator.set_smoothness(smoothness); | |||
| @@ -142,23 +151,23 @@ void Tides::step() { | |||
| // Sync | |||
| // Slight deviation from spec here. | |||
| // Instead of toggling sync by holding the range button, just enable it if the clock port is plugged in. | |||
| generator.set_sync(inputs[CLOCK_INPUT].active && !sheep); | |||
| generator.set_sync(inputs[CLOCK_INPUT].isConnected() && !sheep); | |||
| // Generator | |||
| generator.Process(sheep); | |||
| } | |||
| // Level | |||
| uint16_t level = clamp(inputs[LEVEL_INPUT].normalize(8.0) / 8.0f, 0.0f, 1.0f) * 0xffff; | |||
| uint16_t level = clamp(inputs[LEVEL_INPUT].getNormalVoltage(8.0) / 8.0f, 0.0f, 1.0f) * 0xffff; | |||
| if (level < 32) | |||
| level = 0; | |||
| uint8_t gate = 0; | |||
| if (inputs[FREEZE_INPUT].value >= 0.7) | |||
| if (inputs[FREEZE_INPUT].getVoltage() >= 0.7) | |||
| gate |= tides::CONTROL_FREEZE; | |||
| if (inputs[TRIG_INPUT].value >= 0.7) | |||
| if (inputs[TRIG_INPUT].getVoltage() >= 0.7) | |||
| gate |= tides::CONTROL_GATE; | |||
| if (inputs[CLOCK_INPUT].value >= 0.7) | |||
| if (inputs[CLOCK_INPUT].getVoltage() >= 0.7) | |||
| gate |= tides::CONTROL_CLOCK; | |||
| if (!(lastGate & tides::CONTROL_CLOCK) && (gate & tides::CONTROL_CLOCK)) | |||
| gate |= tides::CONTROL_GATE_RISING; | |||
| @@ -177,33 +186,34 @@ void Tides::step() { | |||
| float unif = (float) uni / 0xffff; | |||
| float bif = (float) bi / 0x8000; | |||
| outputs[HIGH_OUTPUT].value = sample.flags & tides::FLAG_END_OF_ATTACK ? 0.0 : 5.0; | |||
| outputs[LOW_OUTPUT].value = sample.flags & tides::FLAG_END_OF_RELEASE ? 0.0 : 5.0; | |||
| outputs[UNI_OUTPUT].value = unif * 8.0; | |||
| outputs[BI_OUTPUT].value = bif * 5.0; | |||
| outputs[HIGH_OUTPUT].setVoltage(sample.flags & tides::FLAG_END_OF_ATTACK ? 0.0 : 5.0); | |||
| outputs[LOW_OUTPUT].setVoltage(sample.flags & tides::FLAG_END_OF_RELEASE ? 0.0 : 5.0); | |||
| outputs[UNI_OUTPUT].setVoltage(unif * 8.0); | |||
| outputs[BI_OUTPUT].setVoltage(bif * 5.0); | |||
| if (sample.flags & tides::FLAG_END_OF_ATTACK) | |||
| unif *= -1.0; | |||
| lights[PHASE_GREEN_LIGHT].setBrightnessSmooth(fmaxf(0.0, unif)); | |||
| lights[PHASE_RED_LIGHT].setBrightnessSmooth(fmaxf(0.0, -unif)); | |||
| lights[PHASE_GREEN_LIGHT].setSmoothBrightness(fmaxf(0.0, unif), args.sampleTime); | |||
| lights[PHASE_RED_LIGHT].setSmoothBrightness(fmaxf(0.0, -unif), args.sampleTime); | |||
| } | |||
| struct TidesWidget : ModuleWidget { | |||
| SVGPanel *tidesPanel; | |||
| SVGPanel *sheepPanel; | |||
| SvgPanel *tidesPanel; | |||
| SvgPanel *sheepPanel; | |||
| TidesWidget(Tides *module) : ModuleWidget(module) { | |||
| TidesWidget(Tides *module) { | |||
| setModule(module); | |||
| box.size = Vec(15*14, 380); | |||
| { | |||
| tidesPanel = new SVGPanel(); | |||
| tidesPanel->setBackground(SVG::load(assetPlugin(pluginInstance, "res/Tides.svg"))); | |||
| tidesPanel = new SvgPanel(); | |||
| tidesPanel->setBackground(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Tides.svg"))); | |||
| tidesPanel->box.size = box.size; | |||
| addChild(tidesPanel); | |||
| } | |||
| { | |||
| sheepPanel = new SVGPanel(); | |||
| sheepPanel->setBackground(SVG::load(assetPlugin(pluginInstance, "res/Sheep.svg"))); | |||
| sheepPanel = new SvgPanel(); | |||
| sheepPanel->setBackground(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Sheep.svg"))); | |||
| sheepPanel->box.size = box.size; | |||
| addChild(sheepPanel); | |||
| } | |||
| @@ -213,31 +223,31 @@ struct TidesWidget : ModuleWidget { | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(180, 365))); | |||
| addParam(createParam<CKD6>(Vec(19, 52), module, Tides::MODE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<CKD6>(Vec(19, 93), module, Tides::RANGE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<CKD6>(Vec(19, 52), module, Tides::MODE_PARAM)); | |||
| addParam(createParam<CKD6>(Vec(19, 93), module, Tides::RANGE_PARAM)); | |||
| addParam(createParam<Rogan3PSGreen>(Vec(78, 60), module, Tides::FREQUENCY_PARAM, -48.0, 48.0, 0.0)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(156, 66), module, Tides::FM_PARAM, -12.0, 12.0, 0.0)); | |||
| addParam(createParam<Rogan3PSGreen>(Vec(78, 60), module, Tides::FREQUENCY_PARAM)); | |||
| addParam(createParam<Rogan1PSGreen>(Vec(156, 66), module, Tides::FM_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(13, 155), module, Tides::SHAPE_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(85, 155), module, Tides::SLOPE_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(156, 155), module, Tides::SMOOTHNESS_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(13, 155), module, Tides::SHAPE_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(85, 155), module, Tides::SLOPE_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(156, 155), module, Tides::SMOOTHNESS_PARAM)); | |||
| addInput(createPort<PJ301MPort>(Vec(21, 219), PortWidget::INPUT, module, Tides::SHAPE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(93, 219), PortWidget::INPUT, module, Tides::SLOPE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(164, 219), PortWidget::INPUT, module, Tides::SMOOTHNESS_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(21, 219), module, Tides::SHAPE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(93, 219), module, Tides::SLOPE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(164, 219), module, Tides::SMOOTHNESS_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(21, 274), PortWidget::INPUT, module, Tides::TRIG_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(57, 274), PortWidget::INPUT, module, Tides::FREEZE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(93, 274), PortWidget::INPUT, module, Tides::PITCH_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(128, 274), PortWidget::INPUT, module, Tides::FM_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(164, 274), PortWidget::INPUT, module, Tides::LEVEL_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(21, 274), module, Tides::TRIG_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(57, 274), module, Tides::FREEZE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(93, 274), module, Tides::PITCH_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(128, 274), module, Tides::FM_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(164, 274), module, Tides::LEVEL_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(21, 316), PortWidget::INPUT, module, Tides::CLOCK_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(57, 316), PortWidget::OUTPUT, module, Tides::HIGH_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(93, 316), PortWidget::OUTPUT, module, Tides::LOW_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(128, 316), PortWidget::OUTPUT, module, Tides::UNI_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(164, 316), PortWidget::OUTPUT, module, Tides::BI_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(21, 316), module, Tides::CLOCK_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(57, 316), module, Tides::HIGH_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(93, 316), module, Tides::LOW_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(128, 316), module, Tides::UNI_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(164, 316), module, Tides::BI_OUTPUT)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(Vec(56, 61), module, Tides::MODE_GREEN_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(Vec(56, 82), module, Tides::PHASE_GREEN_LIGHT)); | |||
| @@ -84,9 +84,9 @@ struct Tides2 : Module { | |||
| int range; | |||
| tides2::OutputMode output_mode; | |||
| tides2::RampMode ramp_mode; | |||
| BooleanTrigger rangeTrigger; | |||
| BooleanTrigger modeTrigger; | |||
| BooleanTrigger rampTrigger; | |||
| dsp::BooleanTrigger rangeTrigger; | |||
| dsp::BooleanTrigger modeTrigger; | |||
| dsp::BooleanTrigger rampTrigger; | |||
| // Buffers | |||
| tides2::PolySlopeGenerator::OutputSample out[tides2::kBlockSize]; | |||
| @@ -99,7 +99,22 @@ struct Tides2 : Module { | |||
| tides2::OutputMode previous_output_mode = tides2::OUTPUT_MODE_GATES; | |||
| uint8_t frame = 0; | |||
| Tides2() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Tides2() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Tides2::RANGE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Tides2::MODE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Tides2::FREQUENCY_PARAM, -48, 48, 0.0); | |||
| configParam(Tides2::SHAPE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Tides2::RAMP_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Tides2::SMOOTHNESS_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Tides2::SLOPE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Tides2::SHIFT_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Tides2::SLOPE_CV_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Tides2::FREQUENCY_CV_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Tides2::SMOOTHNESS_CV_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Tides2::SHAPE_CV_PARAM, -1.0, 1.0, 0.0); | |||
| configParam(Tides2::SHIFT_CV_PARAM, -1.0, 1.0, 0.0); | |||
| poly_slope_generator.Init(); | |||
| ratio_index_quantizer.Init(); | |||
| memset(&out, 0, sizeof(out)); | |||
| @@ -116,13 +131,13 @@ struct Tides2 : Module { | |||
| } | |||
| void onRandomize() override { | |||
| range = randomu32() % 3; | |||
| output_mode = (tides2::OutputMode) (randomu32() % 4); | |||
| ramp_mode = (tides2::RampMode) (randomu32() % 3); | |||
| range = random::u32() % 3; | |||
| output_mode = (tides2::OutputMode) (random::u32() % 4); | |||
| ramp_mode = (tides2::RampMode) (random::u32() % 3); | |||
| } | |||
| void onSampleRateChange() override { | |||
| ramp_extractor.Init(engineGetSampleRate(), 40.f / engineGetSampleRate()); | |||
| ramp_extractor.Init(APP->engine->getSampleRate(), 40.f / APP->engine->getSampleRate()); | |||
| } | |||
| json_t *dataToJson() override { | |||
| @@ -149,23 +164,23 @@ struct Tides2 : Module { | |||
| ramp_mode = (tides2::RampMode) json_integer_value(rampJ); | |||
| } | |||
| void step() override { | |||
| void process(const ProcessArgs &args) override { | |||
| // Switches | |||
| if (rangeTrigger.process(params[RANGE_PARAM].value > 0.f)) { | |||
| if (rangeTrigger.process(params[RANGE_PARAM].getValue() > 0.f)) { | |||
| range = (range + 1) % 3; | |||
| } | |||
| if (modeTrigger.process(params[MODE_PARAM].value > 0.f)) { | |||
| if (modeTrigger.process(params[MODE_PARAM].getValue() > 0.f)) { | |||
| output_mode = (tides2::OutputMode) ((output_mode + 1) % 4); | |||
| } | |||
| if (rampTrigger.process(params[RAMP_PARAM].value > 0.f)) { | |||
| if (rampTrigger.process(params[RAMP_PARAM].getValue() > 0.f)) { | |||
| ramp_mode = (tides2::RampMode) ((ramp_mode + 1) % 3); | |||
| } | |||
| // Input gates | |||
| trig_flags[frame] = stmlib::ExtractGateFlags(previous_trig_flag, inputs[TRIG_INPUT].value >= 1.7f); | |||
| trig_flags[frame] = stmlib::ExtractGateFlags(previous_trig_flag, inputs[TRIG_INPUT].getVoltage() >= 1.7f); | |||
| previous_trig_flag = trig_flags[frame]; | |||
| clock_flags[frame] = stmlib::ExtractGateFlags(previous_clock_flag, inputs[CLOCK_INPUT].value >= 1.7f); | |||
| clock_flags[frame] = stmlib::ExtractGateFlags(previous_clock_flag, inputs[CLOCK_INPUT].getVoltage() >= 1.7f); | |||
| previous_clock_flag = clock_flags[frame]; | |||
| // Process block | |||
| @@ -173,14 +188,14 @@ struct Tides2 : Module { | |||
| frame = 0; | |||
| tides2::Range range_mode = (range < 2) ? tides2::RANGE_CONTROL : tides2::RANGE_AUDIO; | |||
| float note = clamp(params[FREQUENCY_PARAM].value + 12.f * inputs[V_OCT_INPUT].value, -96.f, 96.f); | |||
| float fm = clamp(params[FREQUENCY_CV_PARAM].value * inputs[FREQUENCY_INPUT].value * 12.f, -96.f, 96.f); | |||
| float note = clamp(params[FREQUENCY_PARAM].getValue() + 12.f * inputs[V_OCT_INPUT].getVoltage(), -96.f, 96.f); | |||
| float fm = clamp(params[FREQUENCY_CV_PARAM].getValue() * inputs[FREQUENCY_INPUT].getVoltage() * 12.f, -96.f, 96.f); | |||
| float transposition = note + fm; | |||
| float ramp[tides2::kBlockSize]; | |||
| float frequency; | |||
| if (inputs[CLOCK_INPUT].active) { | |||
| if (inputs[CLOCK_INPUT].isConnected()) { | |||
| if (must_reset_ramp_extractor) { | |||
| ramp_extractor.Reset(); | |||
| } | |||
| @@ -196,15 +211,15 @@ struct Tides2 : Module { | |||
| must_reset_ramp_extractor = false; | |||
| } | |||
| else { | |||
| frequency = kRootScaled[range] / engineGetSampleRate() * stmlib::SemitonesToRatio(transposition); | |||
| frequency = kRootScaled[range] / args.sampleRate * stmlib::SemitonesToRatio(transposition); | |||
| must_reset_ramp_extractor = true; | |||
| } | |||
| // Get parameters | |||
| float slope = clamp(params[SLOPE_PARAM].value + cubic(params[SLOPE_CV_PARAM].value) * inputs[SLOPE_INPUT].value / 10.f, 0.f, 1.f); | |||
| float shape = clamp(params[SHAPE_PARAM].value + cubic(params[SHAPE_CV_PARAM].value) * inputs[SHAPE_INPUT].value / 10.f, 0.f, 1.f); | |||
| float smoothness = clamp(params[SMOOTHNESS_PARAM].value + cubic(params[SMOOTHNESS_CV_PARAM].value) * inputs[SMOOTHNESS_INPUT].value / 10.f, 0.f, 1.f); | |||
| float shift = clamp(params[SHIFT_PARAM].value + cubic(params[SHIFT_CV_PARAM].value) * inputs[SHIFT_INPUT].value / 10.f, 0.f, 1.f); | |||
| float slope = clamp(params[SLOPE_PARAM].getValue() + dsp::cubic(params[SLOPE_CV_PARAM].getValue()) * inputs[SLOPE_INPUT].getVoltage() / 10.f, 0.f, 1.f); | |||
| float shape = clamp(params[SHAPE_PARAM].getValue() + dsp::cubic(params[SHAPE_CV_PARAM].getValue()) * inputs[SHAPE_INPUT].getVoltage() / 10.f, 0.f, 1.f); | |||
| float smoothness = clamp(params[SMOOTHNESS_PARAM].getValue() + dsp::cubic(params[SMOOTHNESS_CV_PARAM].getValue()) * inputs[SMOOTHNESS_INPUT].getVoltage() / 10.f, 0.f, 1.f); | |||
| float shift = clamp(params[SHIFT_PARAM].getValue() + dsp::cubic(params[SHIFT_CV_PARAM].getValue()) * inputs[SHIFT_INPUT].getVoltage() / 10.f, 0.f, 1.f); | |||
| if (output_mode != previous_output_mode) { | |||
| poly_slope_generator.Reset(); | |||
| @@ -222,7 +237,7 @@ struct Tides2 : Module { | |||
| smoothness, | |||
| shift, | |||
| trig_flags, | |||
| !inputs[TRIG_INPUT].active && inputs[CLOCK_INPUT].active ? ramp : NULL, | |||
| !inputs[TRIG_INPUT].isConnected() && inputs[CLOCK_INPUT].isConnected() ? ramp : NULL, | |||
| out, | |||
| tides2::kBlockSize); | |||
| @@ -238,35 +253,36 @@ struct Tides2 : Module { | |||
| // Outputs | |||
| for (int i = 0; i < 4; i++) { | |||
| float value = out[frame].channel[i]; | |||
| outputs[OUT_OUTPUTS + i].value = value; | |||
| lights[OUTPUT_LIGHTS + i].setBrightnessSmooth(value); | |||
| outputs[OUT_OUTPUTS + i].setVoltage(value); | |||
| lights[OUTPUT_LIGHTS + i].setSmoothBrightness(value, args.sampleTime); | |||
| } | |||
| } | |||
| }; | |||
| struct Tides2Widget : ModuleWidget { | |||
| Tides2Widget(Tides2 *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Tides2.svg"))); | |||
| Tides2Widget(Tides2 *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Tides2.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(7.425, 16.15)), module, Tides2::RANGE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(63.325, 16.15)), module, Tides2::MODE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(16.325, 33.449)), module, Tides2::FREQUENCY_PARAM, -48, 48, 0.0)); | |||
| addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(54.425, 33.449)), module, Tides2::SHAPE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(35.375, 38.699)), module, Tides2::RAMP_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(35.375, 55.549)), module, Tides2::SMOOTHNESS_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(11.575, 60.599)), module, Tides2::SLOPE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(59.175, 60.599)), module, Tides2::SHIFT_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(9.276, 80.599)), module, Tides2::SLOPE_CV_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(22.324, 80.599)), module, Tides2::FREQUENCY_CV_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(35.375, 80.599)), module, Tides2::SMOOTHNESS_CV_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(48.425, 80.599)), module, Tides2::SHAPE_CV_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(61.475, 80.599)), module, Tides2::SHIFT_CV_PARAM, -1.0, 1.0, 0.0)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(7.425, 16.15)), module, Tides2::RANGE_PARAM)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(63.325, 16.15)), module, Tides2::MODE_PARAM)); | |||
| addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(16.325, 33.449)), module, Tides2::FREQUENCY_PARAM)); | |||
| addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(54.425, 33.449)), module, Tides2::SHAPE_PARAM)); | |||
| addParam(createParamCentered<TL1105>(mm2px(Vec(35.375, 38.699)), module, Tides2::RAMP_PARAM)); | |||
| addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(35.375, 55.549)), module, Tides2::SMOOTHNESS_PARAM)); | |||
| addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(11.575, 60.599)), module, Tides2::SLOPE_PARAM)); | |||
| addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(59.175, 60.599)), module, Tides2::SHIFT_PARAM)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(9.276, 80.599)), module, Tides2::SLOPE_CV_PARAM)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(22.324, 80.599)), module, Tides2::FREQUENCY_CV_PARAM)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(35.375, 80.599)), module, Tides2::SMOOTHNESS_CV_PARAM)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(48.425, 80.599)), module, Tides2::SHAPE_CV_PARAM)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(61.475, 80.599)), module, Tides2::SHIFT_CV_PARAM)); | |||
| addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.775, 96.499)), module, Tides2::SLOPE_INPUT)); | |||
| addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.225, 96.499)), module, Tides2::FREQUENCY_INPUT)); | |||
| @@ -39,28 +39,38 @@ struct Veils : Module { | |||
| NUM_LIGHTS | |||
| }; | |||
| Veils() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||
| void step() override; | |||
| Veils() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Veils::GAIN1_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Veils::GAIN2_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Veils::GAIN3_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Veils::GAIN4_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Veils::RESPONSE1_PARAM, 0.0, 1.0, 1.0); | |||
| configParam(Veils::RESPONSE2_PARAM, 0.0, 1.0, 1.0); | |||
| configParam(Veils::RESPONSE3_PARAM, 0.0, 1.0, 1.0); | |||
| configParam(Veils::RESPONSE4_PARAM, 0.0, 1.0, 1.0); | |||
| } | |||
| void process(const ProcessArgs &args) override; | |||
| }; | |||
| void Veils::step() { | |||
| void Veils::process(const ProcessArgs &args) { | |||
| float out = 0.0; | |||
| for (int i = 0; i < 4; i++) { | |||
| float in = inputs[IN1_INPUT + i].value * params[GAIN1_PARAM + i].value; | |||
| if (inputs[CV1_INPUT + i].active) { | |||
| float linear = fmaxf(inputs[CV1_INPUT + i].value / 5.0, 0.0); | |||
| float in = inputs[IN1_INPUT + i].getVoltage() * params[GAIN1_PARAM + i].getValue(); | |||
| if (inputs[CV1_INPUT + i].isConnected()) { | |||
| float linear = fmaxf(inputs[CV1_INPUT + i].getVoltage() / 5.0, 0.0); | |||
| linear = clamp(linear, 0.0f, 2.0f); | |||
| const float base = 200.0; | |||
| float exponential = rescale(powf(base, linear / 2.0f), 1.0f, base, 0.0f, 10.0f); | |||
| in *= crossfade(exponential, linear, params[RESPONSE1_PARAM + i].value); | |||
| in *= crossfade(exponential, linear, params[RESPONSE1_PARAM + i].getValue()); | |||
| } | |||
| out += in; | |||
| lights[OUT1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, out / 5.0)); | |||
| lights[OUT1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -out / 5.0)); | |||
| if (outputs[OUT1_OUTPUT + i].active) { | |||
| outputs[OUT1_OUTPUT + i].value = out; | |||
| lights[OUT1_POS_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, out / 5.0), args.sampleTime); | |||
| lights[OUT1_NEG_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, -out / 5.0), args.sampleTime); | |||
| if (outputs[OUT1_OUTPUT + i].isConnected()) { | |||
| outputs[OUT1_OUTPUT + i].setVoltage(out); | |||
| out = 0.0; | |||
| } | |||
| } | |||
| @@ -68,38 +78,39 @@ void Veils::step() { | |||
| struct VeilsWidget : ModuleWidget { | |||
| VeilsWidget(Veils *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Veils.svg"))); | |||
| VeilsWidget(Veils *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Veils.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(150, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(150, 365))); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 52), module, Veils::GAIN1_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 131), module, Veils::GAIN2_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 210), module, Veils::GAIN3_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 288), module, Veils::GAIN4_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(72, 56), module, Veils::RESPONSE1_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<Trimpot>(Vec(72, 135), module, Veils::RESPONSE2_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<Trimpot>(Vec(72, 214), module, Veils::RESPONSE3_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<Trimpot>(Vec(72, 292), module, Veils::RESPONSE4_PARAM, 0.0, 1.0, 1.0)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 41), PortWidget::INPUT, module, Veils::IN1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 120), PortWidget::INPUT, module, Veils::IN2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 198), PortWidget::INPUT, module, Veils::IN3_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 277), PortWidget::INPUT, module, Veils::IN4_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 80), PortWidget::INPUT, module, Veils::CV1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 159), PortWidget::INPUT, module, Veils::CV2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 238), PortWidget::INPUT, module, Veils::CV3_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(110, 316), PortWidget::INPUT, module, Veils::CV4_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(144, 41), PortWidget::OUTPUT, module, Veils::OUT1_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(144, 120), PortWidget::OUTPUT, module, Veils::OUT2_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(144, 198), PortWidget::OUTPUT, module, Veils::OUT3_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(144, 277), PortWidget::OUTPUT, module, Veils::OUT4_OUTPUT)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 52), module, Veils::GAIN1_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 131), module, Veils::GAIN2_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 210), module, Veils::GAIN3_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(8, 288), module, Veils::GAIN4_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(72, 56), module, Veils::RESPONSE1_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(72, 135), module, Veils::RESPONSE2_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(72, 214), module, Veils::RESPONSE3_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(72, 292), module, Veils::RESPONSE4_PARAM)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 41), module, Veils::IN1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 120), module, Veils::IN2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 198), module, Veils::IN3_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 277), module, Veils::IN4_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 80), module, Veils::CV1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 159), module, Veils::CV2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 238), module, Veils::CV3_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(110, 316), module, Veils::CV4_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(144, 41), module, Veils::OUT1_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(144, 120), module, Veils::OUT2_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(144, 198), module, Veils::OUT3_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(144, 277), module, Veils::OUT4_OUTPUT)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(Vec(152, 87), module, Veils::OUT1_POS_LIGHT)); | |||
| addChild(createLight<MediumLight<GreenRedLight>>(Vec(152, 166), module, Veils::OUT2_POS_LIGHT)); | |||
| @@ -36,10 +36,10 @@ struct Warps : Module { | |||
| warps::Modulator modulator; | |||
| warps::ShortFrame inputFrames[60] = {}; | |||
| warps::ShortFrame outputFrames[60] = {}; | |||
| SchmittTrigger stateTrigger; | |||
| dsp::SchmittTrigger stateTrigger; | |||
| Warps(); | |||
| void step() override; | |||
| void process(const ProcessArgs &args) override; | |||
| json_t *dataToJson() override { | |||
| json_t *rootJ = json_object(); | |||
| @@ -63,20 +63,27 @@ struct Warps : Module { | |||
| void onRandomize() override { | |||
| warps::Parameters *p = modulator.mutable_parameters(); | |||
| p->carrier_shape = randomu32() % 4; | |||
| p->carrier_shape = random::u32() % 4; | |||
| } | |||
| }; | |||
| Warps::Warps() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||
| Warps::Warps() { | |||
| config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||
| configParam(Warps::ALGORITHM_PARAM, 0.0, 8.0, 0.0); | |||
| configParam(Warps::TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||
| configParam(Warps::STATE_PARAM, 0.0, 1.0, 0.0); | |||
| configParam(Warps::LEVEL1_PARAM, 0.0, 1.0, 1.0); | |||
| configParam(Warps::LEVEL2_PARAM, 0.0, 1.0, 1.0); | |||
| memset(&modulator, 0, sizeof(modulator)); | |||
| modulator.Init(96000.0f); | |||
| } | |||
| void Warps::step() { | |||
| void Warps::process(const ProcessArgs &args) { | |||
| // State trigger | |||
| warps::Parameters *p = modulator.mutable_parameters(); | |||
| if (stateTrigger.process(params[STATE_PARAM].value)) { | |||
| if (stateTrigger.process(params[STATE_PARAM].getValue())) { | |||
| p->carrier_shape = (p->carrier_shape + 1) % 4; | |||
| } | |||
| lights[CARRIER_GREEN_LIGHT].value = (p->carrier_shape == 1 || p->carrier_shape == 2) ? 1.0 : 0.0; | |||
| @@ -86,9 +93,9 @@ void Warps::step() { | |||
| if (++frame >= 60) { | |||
| frame = 0; | |||
| p->channel_drive[0] = clamp(params[LEVEL1_PARAM].value + inputs[LEVEL1_INPUT].value / 5.0f, 0.0f, 1.0f); | |||
| p->channel_drive[1] = clamp(params[LEVEL2_PARAM].value + inputs[LEVEL2_INPUT].value / 5.0f, 0.0f, 1.0f); | |||
| p->modulation_algorithm = clamp(params[ALGORITHM_PARAM].value / 8.0f + inputs[ALGORITHM_INPUT].value / 5.0f, 0.0f, 1.0f); | |||
| p->channel_drive[0] = clamp(params[LEVEL1_PARAM].getValue() + inputs[LEVEL1_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||
| p->channel_drive[1] = clamp(params[LEVEL2_PARAM].getValue() + inputs[LEVEL2_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||
| p->modulation_algorithm = clamp(params[ALGORITHM_PARAM].getValue() / 8.0f + inputs[ALGORITHM_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||
| { | |||
| // TODO | |||
| @@ -99,21 +106,21 @@ void Warps::step() { | |||
| lights[ALGORITHM_LIGHT + 2].setBrightness(algorithmColor.b); | |||
| } | |||
| p->modulation_parameter = clamp(params[TIMBRE_PARAM].value + inputs[TIMBRE_INPUT].value / 5.0f, 0.0f, 1.0f); | |||
| p->modulation_parameter = clamp(params[TIMBRE_PARAM].getValue() + inputs[TIMBRE_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||
| p->frequency_shift_pot = params[ALGORITHM_PARAM].value / 8.0; | |||
| p->frequency_shift_cv = clamp(inputs[ALGORITHM_INPUT].value / 5.0f, -1.0f, 1.0f); | |||
| p->frequency_shift_pot = params[ALGORITHM_PARAM].getValue() / 8.0; | |||
| p->frequency_shift_cv = clamp(inputs[ALGORITHM_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f); | |||
| p->phase_shift = p->modulation_algorithm; | |||
| p->note = 60.0 * params[LEVEL1_PARAM].value + 12.0 * inputs[LEVEL1_INPUT].normalize(2.0) + 12.0; | |||
| p->note += log2f(96000.0f * engineGetSampleTime()) * 12.0f; | |||
| p->note = 60.0 * params[LEVEL1_PARAM].getValue() + 12.0 * inputs[LEVEL1_INPUT].getNormalVoltage(2.0) + 12.0; | |||
| p->note += log2f(96000.0f * args.sampleTime) * 12.0f; | |||
| modulator.Process(inputFrames, outputFrames, 60); | |||
| } | |||
| inputFrames[frame].l = clamp((int) (inputs[CARRIER_INPUT].value / 16.0 * 0x8000), -0x8000, 0x7fff); | |||
| inputFrames[frame].r = clamp((int) (inputs[MODULATOR_INPUT].value / 16.0 * 0x8000), -0x8000, 0x7fff); | |||
| outputs[MODULATOR_OUTPUT].value = (float)outputFrames[frame].l / 0x8000 * 5.0; | |||
| outputs[AUX_OUTPUT].value = (float)outputFrames[frame].r / 0x8000 * 5.0; | |||
| inputFrames[frame].l = clamp((int) (inputs[CARRIER_INPUT].getVoltage() / 16.0 * 0x8000), -0x8000, 0x7fff); | |||
| inputFrames[frame].r = clamp((int) (inputs[MODULATOR_INPUT].getVoltage() / 16.0 * 0x8000), -0x8000, 0x7fff); | |||
| outputs[MODULATOR_OUTPUT].setVoltage((float)outputFrames[frame].l / 0x8000 * 5.0); | |||
| outputs[AUX_OUTPUT].setVoltage((float)outputFrames[frame].r / 0x8000 * 5.0); | |||
| } | |||
| @@ -125,30 +132,31 @@ struct AlgorithmLight : RedGreenBlueLight { | |||
| struct WarpsWidget : ModuleWidget { | |||
| WarpsWidget(Warps *module) : ModuleWidget(module) { | |||
| setPanel(SVG::load(assetPlugin(pluginInstance, "res/Warps.svg"))); | |||
| WarpsWidget(Warps *module) { | |||
| setModule(module); | |||
| setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Warps.svg"))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(120, 0))); | |||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||
| addChild(createWidget<ScrewSilver>(Vec(120, 365))); | |||
| addParam(createParam<Rogan6PSWhite>(Vec(29, 52), module, Warps::ALGORITHM_PARAM, 0.0, 8.0, 0.0)); | |||
| addParam(createParam<Rogan6PSWhite>(Vec(29, 52), module, Warps::ALGORITHM_PARAM)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(94, 173), module, Warps::TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||
| addParam(createParam<TL1105>(Vec(16, 182), module, Warps::STATE_PARAM, 0.0, 1.0, 0.0)); | |||
| addParam(createParam<Trimpot>(Vec(14, 213), module, Warps::LEVEL1_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<Trimpot>(Vec(53, 213), module, Warps::LEVEL2_PARAM, 0.0, 1.0, 1.0)); | |||
| addParam(createParam<Rogan1PSWhite>(Vec(94, 173), module, Warps::TIMBRE_PARAM)); | |||
| addParam(createParam<TL1105>(Vec(16, 182), module, Warps::STATE_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(14, 213), module, Warps::LEVEL1_PARAM)); | |||
| addParam(createParam<Trimpot>(Vec(53, 213), module, Warps::LEVEL2_PARAM)); | |||
| addInput(createPort<PJ301MPort>(Vec(8, 273), PortWidget::INPUT, module, Warps::LEVEL1_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(44, 273), PortWidget::INPUT, module, Warps::LEVEL2_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(80, 273), PortWidget::INPUT, module, Warps::ALGORITHM_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(116, 273), PortWidget::INPUT, module, Warps::TIMBRE_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(8, 273), module, Warps::LEVEL1_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(44, 273), module, Warps::LEVEL2_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(80, 273), module, Warps::ALGORITHM_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(116, 273), module, Warps::TIMBRE_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(8, 316), PortWidget::INPUT, module, Warps::CARRIER_INPUT)); | |||
| addInput(createPort<PJ301MPort>(Vec(44, 316), PortWidget::INPUT, module, Warps::MODULATOR_INPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(80, 316), PortWidget::OUTPUT, module, Warps::MODULATOR_OUTPUT)); | |||
| addOutput(createPort<PJ301MPort>(Vec(116, 316), PortWidget::OUTPUT, module, Warps::AUX_OUTPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(8, 316), module, Warps::CARRIER_INPUT)); | |||
| addInput(createInput<PJ301MPort>(Vec(44, 316), module, Warps::MODULATOR_INPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(80, 316), module, Warps::MODULATOR_OUTPUT)); | |||
| addOutput(createOutput<PJ301MPort>(Vec(116, 316), module, Warps::AUX_OUTPUT)); | |||
| addChild(createLight<SmallLight<GreenRedLight>>(Vec(21, 167), module, Warps::CARRIER_GREEN_LIGHT)); | |||