diff --git a/src/AudibleInstruments.hpp b/src/AudibleInstruments.hpp index 86f585b..743943f 100644 --- a/src/AudibleInstruments.hpp +++ b/src/AudibleInstruments.hpp @@ -58,6 +58,7 @@ struct ShadesWidget : ModuleWidget { struct BranchesWidget : ModuleWidget { BranchesWidget(); + Menu *createContextMenu() override; }; struct BlindsWidget : ModuleWidget { diff --git a/src/Blinds.cpp b/src/Blinds.cpp index 2038cea..fd26d29 100644 --- a/src/Blinds.cpp +++ b/src/Blinds.cpp @@ -33,10 +33,10 @@ struct Blinds : Module { NUM_OUTPUTS }; enum LightIds { - IN1_POS_LIGHT, IN1_NEG_LIGHT, - IN2_POS_LIGHT, IN2_NEG_LIGHT, - IN3_POS_LIGHT, IN3_NEG_LIGHT, - IN4_POS_LIGHT, IN4_NEG_LIGHT, + CV1_POS_LIGHT, CV1_NEG_LIGHT, + CV2_POS_LIGHT, CV2_NEG_LIGHT, + CV3_POS_LIGHT, CV3_NEG_LIGHT, + CV4_POS_LIGHT, CV4_NEG_LIGHT, OUT1_POS_LIGHT, OUT1_NEG_LIGHT, OUT2_POS_LIGHT, OUT2_NEG_LIGHT, OUT3_POS_LIGHT, OUT3_NEG_LIGHT, @@ -55,11 +55,12 @@ void Blinds::step() { 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; - lights[IN1_POS_LIGHT + 2*i].setBrightness(fmaxf(0.0, g)); - lights[IN1_NEG_LIGHT + 2*i].setBrightness(fmaxf(0.0, -g)); + g = clampf(g, -2.0, 2.0); + 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].setBrightness(fmaxf(0.0, out)); - lights[OUT1_NEG_LIGHT + 2*i].setBrightness(fmaxf(0.0, -out)); + 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; out = 0.0; @@ -110,13 +111,13 @@ BlindsWidget::BlindsWidget() { addOutput(createOutput(Vec(144, 198), module, Blinds::OUT3_OUTPUT)); addOutput(createOutput(Vec(144, 277), module, Blinds::OUT4_OUTPUT)); - addChild(createLight>(Vec(150, 87), module, Blinds::IN1_POS_LIGHT)); - addChild(createLight>(Vec(150, 166), module, Blinds::IN2_POS_LIGHT)); - addChild(createLight>(Vec(150, 245), module, Blinds::IN3_POS_LIGHT)); - addChild(createLight>(Vec(150, 324), module, Blinds::IN4_POS_LIGHT)); + addChild(createLight>(Vec(77, 96), module, Blinds::CV1_POS_LIGHT)); + addChild(createLight>(Vec(77, 175), module, Blinds::CV2_POS_LIGHT)); + addChild(createLight>(Vec(77, 254), module, Blinds::CV3_POS_LIGHT)); + addChild(createLight>(Vec(77, 333), module, Blinds::CV4_POS_LIGHT)); - addChild(createLight>(Vec(77, 96), module, Blinds::OUT1_POS_LIGHT)); - addChild(createLight>(Vec(77, 175), module, Blinds::OUT2_POS_LIGHT)); - addChild(createLight>(Vec(77, 254), module, Blinds::OUT3_POS_LIGHT)); - addChild(createLight>(Vec(77, 333), module, Blinds::OUT4_POS_LIGHT)); + addChild(createLight>(Vec(150, 87), module, Blinds::OUT1_POS_LIGHT)); + addChild(createLight>(Vec(150, 166), module, Blinds::OUT2_POS_LIGHT)); + addChild(createLight>(Vec(150, 245), module, Blinds::OUT3_POS_LIGHT)); + addChild(createLight>(Vec(150, 324), module, Blinds::OUT4_POS_LIGHT)); } diff --git a/src/Branches.cpp b/src/Branches.cpp index 8e00a11..368a2db 100644 --- a/src/Branches.cpp +++ b/src/Branches.cpp @@ -1,4 +1,5 @@ #include "AudibleInstruments.hpp" +#include "dsp/digital.hpp" struct Branches : Module { @@ -24,41 +25,62 @@ struct Branches : Module { NUM_OUTPUTS }; enum LightIds { - STATE1_LIGHT, - STATE2_LIGHT, + MODE1_LIGHT, + MODE2_LIGHT, + STATE1_POS_LIGHT, STATE1_NEG_LIGHT, + STATE2_POS_LIGHT, STATE2_NEG_LIGHT, NUM_LIGHTS }; - bool lastGate[2] = {}; + SchmittTrigger gateTrigger[2]; + SchmittTrigger modeTrigger[2]; + bool mode[2] = {}; bool outcome[2] = {}; Branches() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} void step() override; + + void reset() override { + for (int i = 0; i < 2; i++) { + mode[i] = false; + outcome[i] = false; + } + } }; void Branches::step() { for (int i = 0; i < 2; i++) { - float out = inputs[IN1_INPUT + i].value; - bool gate = (out >= 1.0); - if (gate && !lastGate[i]) { + // mode button + if (modeTrigger[i].process(params[MODE1_PARAM + i].value)) + mode[i] = !mode[i]; + + float gate = inputs[IN1_INPUT + i].value; + if (gateTrigger[i].process(gate)) { // trigger float r = randomf(); bool toss = (r < params[THRESHOLD1_PARAM + i].value + inputs[P1_INPUT + i].value); - if (params[MODE1_PARAM + i].value < 0.5) { + if (!mode[i]) { // direct mode outcome[i] = toss; } else { // toggle mode - outcome[i] = outcome[i] != toss; + outcome[i] = (outcome[i] != toss); } + + if (!outcome[i]) + lights[STATE1_POS_LIGHT + 2*i].value = 1.0; + else + lights[STATE1_NEG_LIGHT + 2*i].value = 1.0; } - lastGate[i] = gate; - lights[STATE1_LIGHT + i].value = outcome[i] ? out : -out; - outputs[OUT1A_OUTPUT + i].value = outcome[i] ? 0.0 : out; - outputs[OUT1B_OUTPUT + i].value = outcome[i] ? out : 0.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[MODE1_LIGHT + i].value = mode[i] ? 1.0 : 0.0; + + outputs[OUT1A_OUTPUT + i].value = outcome[i] ? 0.0 : gate; + outputs[OUT1B_OUTPUT + i].value = outcome[i] ? gate : 0.0; } } @@ -79,19 +101,44 @@ BranchesWidget::BranchesWidget() { addChild(createScrew(Vec(15, 365))); addParam(createParam(Vec(24, 64), module, Branches::THRESHOLD1_PARAM, 0.0, 1.0, 0.5)); - // addParam(createParam(Vec(69, 58), module, Branches::MODE1_PARAM, 0.0, 1.0, 0.0)); + addParam(createParam(Vec(69, 58), module, Branches::MODE1_PARAM, 0.0, 1.0, 0.0)); addInput(createInput(Vec(9, 122), module, Branches::IN1_INPUT)); addInput(createInput(Vec(55, 122), module, Branches::P1_INPUT)); addOutput(createOutput(Vec(9, 160), module, Branches::OUT1A_OUTPUT)); addOutput(createOutput(Vec(55, 160), module, Branches::OUT1B_OUTPUT)); addParam(createParam(Vec(24, 220), module, Branches::THRESHOLD2_PARAM, 0.0, 1.0, 0.5)); - // addParam(createParam(Vec(69, 214), module, Branches::MODE2_PARAM, 0.0, 1.0, 0.0)); + addParam(createParam(Vec(69, 214), module, Branches::MODE2_PARAM, 0.0, 1.0, 0.0)); addInput(createInput(Vec(9, 278), module, Branches::IN2_INPUT)); addInput(createInput(Vec(55, 278), module, Branches::P2_INPUT)); addOutput(createOutput(Vec(9, 316), module, Branches::OUT2A_OUTPUT)); addOutput(createOutput(Vec(55, 316), module, Branches::OUT2B_OUTPUT)); - addChild(createLight>(Vec(40, 169), module, Branches::STATE1_LIGHT)); - addChild(createLight>(Vec(40, 325), module, Branches::STATE2_LIGHT)); + addChild(createLight>(Vec(40, 169), module, Branches::STATE1_POS_LIGHT)); + addChild(createLight>(Vec(40, 325), module, Branches::STATE2_POS_LIGHT)); +} + +struct BranchesModeItem : MenuItem { + Branches *branches; + int channel; + void onAction() override { + branches->mode[channel] ^= 1; + } + void step() override { + rightText = branches->mode[channel] ? "Toggle" : "Latch"; + } +}; + +Menu *BranchesWidget::createContextMenu() { + Menu *menu = ModuleWidget::createContextMenu(); + + Branches *branches = dynamic_cast(module); + assert(branches); + + menu->pushChild(construct()); + menu->pushChild(construct(&MenuEntry::text, "Channels")); + menu->pushChild(construct(&MenuEntry::text, "Channel 1 mode", &BranchesModeItem::branches, branches, &BranchesModeItem::channel, 0)); + menu->pushChild(construct(&MenuEntry::text, "Channel 2 mode", &BranchesModeItem::branches, branches, &BranchesModeItem::channel, 1)); + + return menu; } diff --git a/src/Elements.cpp b/src/Elements.cpp index 793f615..3057af8 100644 --- a/src/Elements.cpp +++ b/src/Elements.cpp @@ -67,6 +67,7 @@ struct Elements : Module { NUM_OUTPUTS }; enum LightIds { + GATE_LIGHT, EXCITER_LIGHT, RESONATOR_LIGHT, NUM_LIGHTS @@ -198,8 +199,9 @@ void Elements::step() { } // Set lights - lights[EXCITER_LIGHT].value = part->exciter_level(); - lights[RESONATOR_LIGHT].value = part->resonator_level(); + lights[GATE_LIGHT].setBrightness(performance.gate ? 0.5 : 0.0); + lights[EXCITER_LIGHT].setBrightness(part->exciter_level()); + lights[RESONATOR_LIGHT].setBrightness(part->resonator_level()); } // Set output @@ -284,6 +286,10 @@ ElementsWidget::ElementsWidget() { addParam(createParam(Vec(36, 116), module, Elements::PLAY_PARAM, 0.0, 1.0, 0.0)); + ModuleLightWidget *gateLight = createLight(Vec(36+3, 116+3), module, Elements::GATE_LIGHT); + gateLight->bgColor = COLOR_BLACK_TRANSPARENT; + gateLight->box.size = Vec(28-6, 28-6); + addChild(gateLight); addChild(createLight>(Vec(184, 165), module, Elements::EXCITER_LIGHT)); addChild(createLight>(Vec(395, 165), module, Elements::RESONATOR_LIGHT)); } @@ -306,9 +312,9 @@ Menu *ElementsWidget::createContextMenu() { assert(elements); menu->pushChild(construct()); - menu->pushChild(construct(&MenuEntry::text, "Alternative Models")); + menu->pushChild(construct(&MenuEntry::text, "Alternative models")); menu->pushChild(construct(&MenuEntry::text, "Original", &ElementsModalItem::elements, elements, &ElementsModalItem::model, 0)); - menu->pushChild(construct(&MenuEntry::text, "Non-Linear String", &ElementsModalItem::elements, elements, &ElementsModalItem::model, 1)); + menu->pushChild(construct(&MenuEntry::text, "Non-linear string", &ElementsModalItem::elements, elements, &ElementsModalItem::model, 1)); menu->pushChild(construct(&MenuEntry::text, "Chords", &ElementsModalItem::elements, elements, &ElementsModalItem::model, 2)); return menu; diff --git a/src/Frames.cpp b/src/Frames.cpp index cea082b..8a55999 100644 --- a/src/Frames.cpp +++ b/src/Frames.cpp @@ -222,7 +222,7 @@ void Frames::step() { // Set lights for (int i = 0; i < 4; i++) { - lights[GAIN1_LIGHT + i].value = gains[i]; + lights[GAIN1_LIGHT + i].setBrightness(gains[i]); } if (poly_lfo_mode) { @@ -240,8 +240,10 @@ void Frames::step() { else { colors = keyframer.color(); } - for (int c = 0; c < 3; c++) { - lights[FRAME_LIGHT + c].value = colors[c] / 255.0; + for (int i = 0; i < 3; i++) { + float c = colors[i] / 255.0; + c = 1.0 - (1.0 - c) * 1.25; + lights[FRAME_LIGHT + i].setBrightness(c); } } diff --git a/src/Shades.cpp b/src/Shades.cpp index 5e8c1fe..2cce679 100644 --- a/src/Shades.cpp +++ b/src/Shades.cpp @@ -75,13 +75,13 @@ ShadesWidget::ShadesWidget() { addChild(createScrew(Vec(15, 0))); addChild(createScrew(Vec(15, 365))); - addParam(createParam(Vec(40, 41), module, Shades::GAIN1_PARAM, 0.0, 1.0, 0.0)); - addParam(createParam(Vec(40, 107), module, Shades::GAIN2_PARAM, 0.0, 1.0, 0.0)); - addParam(createParam(Vec(40, 173), module, Shades::GAIN3_PARAM, 0.0, 1.0, 0.0)); + addParam(createParam(Vec(40, 41), module, Shades::GAIN1_PARAM, 0.0, 1.0, 0.5)); + addParam(createParam(Vec(40, 107), module, Shades::GAIN2_PARAM, 0.0, 1.0, 0.5)); + addParam(createParam(Vec(40, 173), module, Shades::GAIN3_PARAM, 0.0, 1.0, 0.5)); - addParam(createParam(Vec(10, 52), module, Shades::MODE1_PARAM, 0.0, 1.0, 0.0)); - addParam(createParam(Vec(10, 118), module, Shades::MODE2_PARAM, 0.0, 1.0, 0.0)); - addParam(createParam(Vec(10, 184), module, Shades::MODE3_PARAM, 0.0, 1.0, 0.0)); + addParam(createParam(Vec(10, 52), module, Shades::MODE1_PARAM, 0.0, 1.0, 1.0)); + addParam(createParam(Vec(10, 118), module, Shades::MODE2_PARAM, 0.0, 1.0, 1.0)); + addParam(createParam(Vec(10, 184), module, Shades::MODE3_PARAM, 0.0, 1.0, 1.0)); addInput(createInput(Vec(9, 245), module, Shades::IN1_INPUT)); addInput(createInput(Vec(9, 281), module, Shades::IN2_INPUT)); diff --git a/src/Tides.cpp b/src/Tides.cpp index 61a4383..80ea179 100644 --- a/src/Tides.cpp +++ b/src/Tides.cpp @@ -102,16 +102,16 @@ void Tides::step() { mode = (tides::GeneratorMode) (((int)mode - 1 + 3) % 3); generator.set_mode(mode); } - lights[MODE_GREEN_LIGHT].value = (mode == 0 || mode == 1) ? 1.0 : 0.0; - lights[MODE_RED_LIGHT].value = (mode == 1 || mode == 2) ? 1.0 : 0.0; + lights[MODE_GREEN_LIGHT].value = (mode == 2) ? 1.0 : 0.0; + lights[MODE_RED_LIGHT].value = (mode == 0) ? 1.0 : 0.0; tides::GeneratorRange range = generator.range(); if (rangeTrigger.process(params[RANGE_PARAM].value)) { range = (tides::GeneratorRange) (((int)range - 1 + 3) % 3); generator.set_range(range); } - lights[RANGE_GREEN_LIGHT].value = (range == 0 || range == 1) ? 1.0 : 0.0; - lights[RANGE_RED_LIGHT].value = (range == 1 || range == 2) ? 1.0 : 0.0; + lights[RANGE_GREEN_LIGHT].value = (range == 2) ? 1.0 : 0.0; + lights[RANGE_RED_LIGHT].value = (range == 0) ? 1.0 : 0.0; // Buffer loop if (++frame >= 16) { diff --git a/src/Veils.cpp b/src/Veils.cpp index bdf13ad..7e6c7d2 100644 --- a/src/Veils.cpp +++ b/src/Veils.cpp @@ -52,8 +52,9 @@ void Veils::step() { 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); - const float ex = 200.0; - float exponential = rescalef(powf(ex, linear), 1.0, ex, 0.0, 1.0); + linear = clampf(linear, 0.0, 2.0); + const float base = 200.0; + float exponential = rescalef(powf(base, linear / 2.0), 1.0, base, 0.0, 10.0); in *= crossf(exponential, linear, params[RESPONSE1_PARAM + i].value); } out += in; diff --git a/src/Warps.cpp b/src/Warps.cpp index 0f869f5..6006435 100644 --- a/src/Warps.cpp +++ b/src/Warps.cpp @@ -97,10 +97,10 @@ void Warps::step() { { // TODO // Use the correct light color - NVGcolor algorithmColor = nvgHSL(p->modulation_algorithm, 0.5, 0.5); - lights[ALGORITHM_LIGHT + 0].value = algorithmColor.r; - lights[ALGORITHM_LIGHT + 1].value = algorithmColor.g; - lights[ALGORITHM_LIGHT + 2].value = algorithmColor.b; + NVGcolor algorithmColor = nvgHSL(p->modulation_algorithm, 0.3, 0.4); + lights[ALGORITHM_LIGHT + 0].setBrightness(algorithmColor.r); + lights[ALGORITHM_LIGHT + 1].setBrightness(algorithmColor.g); + lights[ALGORITHM_LIGHT + 2].setBrightness(algorithmColor.b); } p->modulation_parameter = clampf(params[TIMBRE_PARAM].value + inputs[TIMBRE_INPUT].value / 5.0, 0.0, 1.0);