diff --git a/include/componentlibrary.hpp b/include/componentlibrary.hpp index c43e3f56..6e6442c7 100644 --- a/include/componentlibrary.hpp +++ b/include/componentlibrary.hpp @@ -302,179 +302,234 @@ struct Davies1900hLargeRedKnob : Davies1900hKnob { struct Rogan : app::SvgKnob { + widget::SvgWidget* bg; + widget::SvgWidget* fg; + Rogan() { minAngle = -0.83 * M_PI; maxAngle = 0.83 * M_PI; + + bg = new widget::SvgWidget; + fb->addChildBelow(bg, tw); + + fg = new widget::SvgWidget; + fb->addChildAbove(fg, tw); } }; struct Rogan6PSWhite : Rogan { Rogan6PSWhite() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan6PSWhite.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan5PSGray : Rogan { Rogan5PSGray() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan5PSGray.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan3PSBlue : Rogan { Rogan3PSBlue() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSBlue.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan3PSRed : Rogan { Rogan3PSRed() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSRed.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan3PSGreen : Rogan { Rogan3PSGreen() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSGreen.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan3PSWhite : Rogan { Rogan3PSWhite() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite.svg"))); - - widget::SvgWidget* bg = new widget::SvgWidget; bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); - fb->addChildBelow(bg, tw); - - widget::SvgWidget* fg = new widget::SvgWidget; fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); - fb->addChildAbove(fg, tw); } }; struct Rogan3PBlue : Rogan { Rogan3PBlue() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PBlue.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan3PRed : Rogan { Rogan3PRed() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PRed.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan3PGreen : Rogan { Rogan3PGreen() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PGreen.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan3PWhite : Rogan { Rogan3PWhite() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PWhite.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2SGray : Rogan { Rogan2SGray() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2SGray.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2PSBlue : Rogan { Rogan2PSBlue() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PSBlue.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2PSRed : Rogan { Rogan2PSRed() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PSRed.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2PSGreen : Rogan { Rogan2PSGreen() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PSGreen.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2PSWhite : Rogan { Rogan2PSWhite() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PSWhite.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2PBlue : Rogan { Rogan2PBlue() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PBlue.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2PRed : Rogan { Rogan2PRed() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PRed.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2PGreen : Rogan { Rogan2PGreen() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PGreen.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan2PWhite : Rogan { Rogan2PWhite() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PWhite.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan1PSBlue : Rogan { Rogan1PSBlue() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PSBlue.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan1PSRed : Rogan { Rogan1PSRed() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PSRed.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan1PSGreen : Rogan { Rogan1PSGreen() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PSGreen.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan1PSWhite : Rogan { Rogan1PSWhite() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PSWhite.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan1PBlue : Rogan { Rogan1PBlue() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PBlue.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan1PRed : Rogan { Rogan1PRed() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PRed.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan1PGreen : Rogan { Rogan1PGreen() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PGreen.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; struct Rogan1PWhite : Rogan { Rogan1PWhite() { setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PWhite.svg"))); + bg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-bg.svg"))); + fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg"))); } }; diff --git a/src/core/MIDI_CC.cpp b/src/core/MIDI_CC.cpp index 490f2a8e..06a96a98 100644 --- a/src/core/MIDI_CC.cpp +++ b/src/core/MIDI_CC.cpp @@ -21,6 +21,7 @@ struct MIDI_CC : Module { }; midi::InputQueue midiInput; + /** [cc][channel] */ int8_t ccValues[128][16]; /** When LSB is enabled for CC 0-31, the MSB is stored here until the LSB is received. @@ -33,7 +34,7 @@ struct MIDI_CC : Module { dsp::ExponentialFilter valueFilters[16][16]; bool smooth; bool mpeMode; - bool lsbEnabled; + bool lsbMode; MIDI_CC() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); @@ -66,7 +67,7 @@ struct MIDI_CC : Module { midiInput.reset(); smooth = true; mpeMode = false; - lsbEnabled = false; + lsbMode = false; } void process(const ProcessArgs& args) override { @@ -80,6 +81,7 @@ struct MIDI_CC : Module { } int channels = mpeMode ? 16 : 1; + for (int i = 0; i < 16; i++) { if (!outputs[CC_OUTPUT + i].isConnected()) continue; @@ -89,7 +91,7 @@ struct MIDI_CC : Module { for (int c = 0; c < channels; c++) { int16_t cellValue = int16_t(ccValues[cc][c]) * 128; - if (lsbEnabled && cc < 32) + if (lsbMode && cc < 32) cellValue += ccValues[cc + 32][c]; // Maximum value for 14-bit CC should be MSB=127 LSB=0, not MSB=127 LSB=127, because this is the maximum value that 7-bit controllers can send. float value = float(cellValue) / (128 * 127); @@ -135,11 +137,11 @@ struct MIDI_CC : Module { learningId = -1; } - if (lsbEnabled && cc < 32) { + if (lsbMode && cc < 32) { // Don't set MSB yet. Wait for LSB to be received. msbValues[cc][c] = value; } - else if (lsbEnabled && 32 <= cc && cc < 64) { + else if (lsbMode && 32 <= cc && cc < 64) { // Apply MSB when LSB is received ccValues[cc - 32][c] = msbValues[cc - 32][c]; ccValues[cc][c] = value; @@ -170,7 +172,7 @@ struct MIDI_CC : Module { json_object_set_new(rootJ, "smooth", json_boolean(smooth)); json_object_set_new(rootJ, "mpeMode", json_boolean(mpeMode)); - json_object_set_new(rootJ, "lsbEnabled", json_boolean(lsbEnabled)); + json_object_set_new(rootJ, "lsbMode", json_boolean(lsbMode)); return rootJ; } @@ -206,9 +208,9 @@ struct MIDI_CC : Module { if (mpeModeJ) mpeMode = json_boolean_value(mpeModeJ); - json_t* lsbEnabledJ = json_object_get(rootJ, "lsbEnabled"); + json_t* lsbEnabledJ = json_object_get(rootJ, "lsbMode"); if (lsbEnabledJ) - lsbEnabled = json_boolean_value(lsbEnabledJ); + lsbMode = json_boolean_value(lsbEnabledJ); } }; @@ -259,7 +261,6 @@ struct MIDI_CCWidget : ModuleWidget { module->smooth ^= true; } }; - SmoothItem* smoothItem = new SmoothItem; smoothItem->text = "Smooth CC"; smoothItem->rightText = CHECKMARK(module->smooth); @@ -272,25 +273,23 @@ struct MIDI_CCWidget : ModuleWidget { module->mpeMode ^= true; } }; - MpeModeItem* mpeModeItem = new MpeModeItem; mpeModeItem->text = "MPE mode"; mpeModeItem->rightText = CHECKMARK(module->mpeMode); mpeModeItem->module = module; menu->addChild(mpeModeItem); - struct LSBItem : MenuItem { + struct LsbModeItem : MenuItem { MIDI_CC* module; void onAction(const ActionEvent& e) override { - module->lsbEnabled ^= true; + module->lsbMode ^= true; } }; - - LSBItem* highResolutionItem = new LSBItem; - highResolutionItem->text = "CC 0-31 controls are 14-bit"; - highResolutionItem->rightText = CHECKMARK(module->lsbEnabled); - highResolutionItem->module = module; - menu->addChild(highResolutionItem); + LsbModeItem* lsbItem = new LsbModeItem; + lsbItem->text = "CC 0-31 controls are 14-bit"; + lsbItem->rightText = CHECKMARK(module->lsbMode); + lsbItem->module = module; + menu->addChild(lsbItem); } }; diff --git a/src/core/MIDI_CV.cpp b/src/core/MIDI_CV.cpp index ec495758..07297bf0 100644 --- a/src/core/MIDI_CV.cpp +++ b/src/core/MIDI_CV.cpp @@ -15,11 +15,11 @@ struct MIDI_CV : Module { NUM_INPUTS }; enum OutputIds { - CV_OUTPUT, + PITCH_OUTPUT, GATE_OUTPUT, VELOCITY_OUTPUT, AFTERTOUCH_OUTPUT, - PITCH_OUTPUT, + PW_OUTPUT, MOD_OUTPUT, RETRIGGER_OUTPUT, CLOCK_OUTPUT, @@ -59,10 +59,14 @@ struct MIDI_CV : Module { int rotateIndex; - // 16 channels for MPE. When MPE is disabled, only the first channel is used. - uint16_t pitches[16]; + /** Pitch wheel. + When MPE is disabled, only the first channel is used. + [channel] + */ + uint16_t pws[16]; + /** [channel] */ uint8_t mods[16]; - dsp::ExponentialFilter pitchFilters[16]; + dsp::ExponentialFilter pwFilters[16]; dsp::ExponentialFilter modFilters[16]; dsp::PulseGenerator clockPulse; @@ -74,11 +78,11 @@ struct MIDI_CV : Module { MIDI_CV() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); - configOutput(CV_OUTPUT, "V/oct"); + configOutput(PITCH_OUTPUT, "Pitch (1V/oct)"); configOutput(GATE_OUTPUT, "Gate"); configOutput(VELOCITY_OUTPUT, "Velocity"); configOutput(AFTERTOUCH_OUTPUT, "Aftertouch"); - configOutput(PITCH_OUTPUT, "Pitch wheel"); + configOutput(PW_OUTPUT, "Pitch wheel"); configOutput(MOD_OUTPUT, "Mod wheel"); configOutput(RETRIGGER_OUTPUT, "Retrigger"); configOutput(CLOCK_OUTPUT, "Clock"); @@ -88,7 +92,7 @@ struct MIDI_CV : Module { configOutput(CONTINUE_OUTPUT, "Continue"); heldNotes.reserve(128); for (int c = 0; c < 16; c++) { - pitchFilters[c].setTau(1 / 30.f); + pwFilters[c].setTau(1 / 30.f); modFilters[c].setTau(1 / 30.f); } onReset(); @@ -110,9 +114,9 @@ struct MIDI_CV : Module { gates[c] = false; velocities[c] = 0; aftertouches[c] = 0; - pitches[c] = 8192; + pws[c] = 8192; mods[c] = 0; - pitchFilters[c].reset(); + pwFilters[c].reset(); modFilters[c].reset(); } pedal = false; @@ -130,13 +134,13 @@ struct MIDI_CV : Module { midiInput.queue.pop(); } - outputs[CV_OUTPUT].setChannels(channels); + outputs[PITCH_OUTPUT].setChannels(channels); outputs[GATE_OUTPUT].setChannels(channels); outputs[VELOCITY_OUTPUT].setChannels(channels); outputs[AFTERTOUCH_OUTPUT].setChannels(channels); outputs[RETRIGGER_OUTPUT].setChannels(channels); for (int c = 0; c < channels; c++) { - outputs[CV_OUTPUT].setVoltage((notes[c] - 60.f) / 12.f, c); + outputs[PITCH_OUTPUT].setVoltage((notes[c] - 60.f) / 12.f, c); outputs[GATE_OUTPUT].setVoltage(gates[c] ? 10.f : 0.f, c); outputs[VELOCITY_OUTPUT].setVoltage(rescale(velocities[c], 0, 127, 0.f, 10.f), c); outputs[AFTERTOUCH_OUTPUT].setVoltage(rescale(aftertouches[c], 0, 127, 0.f, 10.f), c); @@ -144,37 +148,25 @@ struct MIDI_CV : Module { } // Set pitch and mod wheel - auto updatePitch = [&](int c) { - float pitch = ((int) pitches[c] - 8192) / 8191.f; - pitch = clamp(pitch, -1.f, 1.f); + int wheelChannels = (polyMode == MPE_MODE) ? 16 : 1; + outputs[PW_OUTPUT].setChannels(wheelChannels); + outputs[MOD_OUTPUT].setChannels(wheelChannels); + for (int c = 0; c < wheelChannels; c++) { + float pw = ((int) pws[c] - 8192) / 8191.f; + pw = clamp(pw, -1.f, 1.f); if (smooth) - pitch = pitchFilters[c].process(args.sampleTime, pitch); + pw = pwFilters[c].process(args.sampleTime, pw); else - pitchFilters[c].out = pitch; - outputs[PITCH_OUTPUT].setVoltage(pitchFilters[c].out * 5.f); - }; - auto updateMod = [&](int c) { + pwFilters[c].out = pw; + outputs[PW_OUTPUT].setVoltage(pw * 5.f); + float mod = mods[c] / 127.f; mod = clamp(mod, 0.f, 1.f); if (smooth) - modFilters[c].process(args.sampleTime, mod); + mod = modFilters[c].process(args.sampleTime, mod); else modFilters[c].out = mod; - outputs[MOD_OUTPUT].setVoltage(modFilters[c].out * 10.f); - }; - if (polyMode == MPE_MODE) { - for (int c = 0; c < channels; c++) { - updatePitch(c); - outputs[PITCH_OUTPUT].setChannels(1); - updateMod(c); - outputs[MOD_OUTPUT].setChannels(1); - } - } - else { - updatePitch(0); - outputs[PITCH_OUTPUT].setChannels(1); - updateMod(0); - outputs[MOD_OUTPUT].setChannels(1); + outputs[MOD_OUTPUT].setVoltage(mod * 10.f); } outputs[CLOCK_OUTPUT].setVoltage(clockPulse.process(args.sampleTime) ? 10.f : 0.f); @@ -233,7 +225,7 @@ struct MIDI_CV : Module { // pitch wheel case 0xe: { int c = (polyMode == MPE_MODE) ? msg.getChannel() : 0; - pitches[c] = ((uint16_t) msg.getValue() << 7) | msg.getNote(); + pws[c] = ((uint16_t) msg.getValue() << 7) | msg.getNote(); } break; case 0xf: { processSystem(msg); @@ -440,7 +432,7 @@ struct MIDI_CV : Module { json_object_set_new(rootJ, "clockDivision", json_integer(clockDivision)); // Saving/restoring pitch and mod doesn't make much sense for MPE. if (polyMode != MPE_MODE) { - json_object_set_new(rootJ, "lastPitch", json_integer(pitches[0])); + json_object_set_new(rootJ, "lastPitch", json_integer(pws[0])); json_object_set_new(rootJ, "lastMod", json_integer(mods[0])); } json_object_set_new(rootJ, "midi", midiInput.toJson()); @@ -466,7 +458,7 @@ struct MIDI_CV : Module { json_t* lastPitchJ = json_object_get(rootJ, "lastPitch"); if (lastPitchJ) - pitches[0] = json_integer_value(lastPitchJ); + pws[0] = json_integer_value(lastPitchJ); json_t* lastModJ = json_object_get(rootJ, "lastMod"); if (lastModJ) @@ -489,11 +481,11 @@ struct MIDI_CVWidget : ModuleWidget { addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - addOutput(createOutput(mm2px(Vec(4.61505, 60.1445)), module, MIDI_CV::CV_OUTPUT)); + addOutput(createOutput(mm2px(Vec(4.61505, 60.1445)), module, MIDI_CV::PITCH_OUTPUT)); addOutput(createOutput(mm2px(Vec(16.214, 60.1445)), module, MIDI_CV::GATE_OUTPUT)); addOutput(createOutput(mm2px(Vec(27.8143, 60.1445)), module, MIDI_CV::VELOCITY_OUTPUT)); addOutput(createOutput(mm2px(Vec(4.61505, 76.1449)), module, MIDI_CV::AFTERTOUCH_OUTPUT)); - addOutput(createOutput(mm2px(Vec(16.214, 76.1449)), module, MIDI_CV::PITCH_OUTPUT)); + addOutput(createOutput(mm2px(Vec(16.214, 76.1449)), module, MIDI_CV::PW_OUTPUT)); addOutput(createOutput(mm2px(Vec(27.8143, 76.1449)), module, MIDI_CV::MOD_OUTPUT)); addOutput(createOutput(mm2px(Vec(4.61505, 92.1439)), module, MIDI_CV::CLOCK_OUTPUT)); addOutput(createOutput(mm2px(Vec(16.214, 92.1439)), module, MIDI_CV::CLOCK_DIV_OUTPUT)); @@ -519,7 +511,6 @@ struct MIDI_CVWidget : ModuleWidget { module->smooth ^= true; } }; - SmoothItem* smoothItem = new SmoothItem; smoothItem->text = "Smooth pitch/mod wheel"; smoothItem->rightText = CHECKMARK(module->smooth); @@ -533,7 +524,6 @@ struct MIDI_CVWidget : ModuleWidget { module->clockDivision = clockDivision; } }; - struct ClockDivisionItem : MenuItem { MIDI_CV* module; Menu* createChildMenu() override { @@ -551,7 +541,6 @@ struct MIDI_CVWidget : ModuleWidget { return menu; } }; - ClockDivisionItem* clockDivisionItem = new ClockDivisionItem; clockDivisionItem->text = "CLK/N divider"; clockDivisionItem->rightText = RIGHT_ARROW; @@ -565,7 +554,6 @@ struct MIDI_CVWidget : ModuleWidget { module->setChannels(channels); } }; - struct ChannelItem : MenuItem { MIDI_CV* module; Menu* createChildMenu() override { @@ -584,7 +572,6 @@ struct MIDI_CVWidget : ModuleWidget { return menu; } }; - ChannelItem* channelItem = new ChannelItem; channelItem->text = "Polyphony channels"; channelItem->rightText = string::f("%d", module->channels) + " " + RIGHT_ARROW; @@ -598,7 +585,6 @@ struct MIDI_CVWidget : ModuleWidget { module->setPolyMode(polyMode); } }; - struct PolyModeItem : MenuItem { MIDI_CV* module; Menu* createChildMenu() override { @@ -621,7 +607,6 @@ struct MIDI_CVWidget : ModuleWidget { return menu; } }; - PolyModeItem* polyModeItem = new PolyModeItem; polyModeItem->text = "Polyphony mode"; polyModeItem->rightText = RIGHT_ARROW; @@ -634,7 +619,6 @@ struct MIDI_CVWidget : ModuleWidget { module->panic(); } }; - PanicItem* panicItem = new PanicItem; panicItem->text = "Panic"; panicItem->module = module; diff --git a/src/core/MIDI_Gate.cpp b/src/core/MIDI_Gate.cpp index 49ca1bc2..aaf1309d 100644 --- a/src/core/MIDI_Gate.cpp +++ b/src/core/MIDI_Gate.cpp @@ -13,7 +13,7 @@ struct MIDI_Gate : Module { NUM_INPUTS }; enum OutputIds { - ENUMS(TRIG_OUTPUT, 16), + ENUMS(GATE_OUTPUTS, 16), NUM_OUTPUTS }; enum LightIds { @@ -22,21 +22,23 @@ struct MIDI_Gate : Module { midi::InputQueue midiInput; - /** [cell][c] */ + /** [cell][channel] */ bool gates[16][16]; - /** [cell][c] */ + /** [cell][channel] */ float gateTimes[16][16]; - /** [cell][c] */ + /** [cell][channel] */ uint8_t velocities[16][16]; - int learningId = -1; - uint8_t learnedNotes[16] = {}; - bool velocityMode = false; - bool mpeMode = false; + /** Cell ID in learn mode, or -1 if none. */ + int learningId; + /** [cell] */ + uint8_t learnedNotes[16]; + bool velocityMode; + bool mpeMode; MIDI_Gate() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); for (int i = 0; i < 16; i++) - configOutput(TRIG_OUTPUT + i, string::f("Cell %d", i + 1)); + configOutput(GATE_OUTPUTS + i, string::f("Gate %d", i + 1)); onReset(); } @@ -76,16 +78,16 @@ struct MIDI_Gate : Module { int channels = mpeMode ? 16 : 1; for (int i = 0; i < 16; i++) { - outputs[TRIG_OUTPUT + i].setChannels(channels); + outputs[GATE_OUTPUTS + i].setChannels(channels); for (int c = 0; c < channels; c++) { // Make sure all pulses last longer than 1ms if (gates[i][c] || gateTimes[i][c] > 0.f) { float velocity = velocityMode ? (velocities[i][c] / 127.f) : 1.f; - outputs[TRIG_OUTPUT + i].setVoltage(velocity * 10.f, c); + outputs[GATE_OUTPUTS + i].setVoltage(velocity * 10.f, c); gateTimes[i][c] -= args.sampleTime; } else { - outputs[TRIG_OUTPUT + i].setVoltage(0.f, c); + outputs[GATE_OUTPUTS + i].setVoltage(0.f, c); } } } @@ -181,30 +183,6 @@ struct MIDI_Gate : Module { }; -struct MIDI_GateVelocityItem : MenuItem { - MIDI_Gate* module; - void onAction(const ActionEvent& e) override { - module->velocityMode ^= true; - } -}; - - -struct MIDI_GateMpeModeItem : MenuItem { - MIDI_Gate* module; - void onAction(const ActionEvent& e) override { - module->mpeMode ^= true; - } -}; - - -struct MIDI_GatePanicItem : MenuItem { - MIDI_Gate* module; - void onAction(const ActionEvent& e) override { - module->panic(); - } -}; - - struct MIDI_GateWidget : ModuleWidget { MIDI_GateWidget(MIDI_Gate* module) { setModule(module); @@ -215,22 +193,22 @@ struct MIDI_GateWidget : ModuleWidget { addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - addOutput(createOutput(mm2px(Vec(3.894335, 73.344704)), module, MIDI_Gate::TRIG_OUTPUT + 0)); - addOutput(createOutput(mm2px(Vec(15.494659, 73.344704)), module, MIDI_Gate::TRIG_OUTPUT + 1)); - addOutput(createOutput(mm2px(Vec(27.094982, 73.344704)), module, MIDI_Gate::TRIG_OUTPUT + 2)); - addOutput(createOutput(mm2px(Vec(38.693932, 73.344704)), module, MIDI_Gate::TRIG_OUTPUT + 3)); - addOutput(createOutput(mm2px(Vec(3.8943355, 84.945023)), module, MIDI_Gate::TRIG_OUTPUT + 4)); - addOutput(createOutput(mm2px(Vec(15.49466, 84.945023)), module, MIDI_Gate::TRIG_OUTPUT + 5)); - addOutput(createOutput(mm2px(Vec(27.094982, 84.945023)), module, MIDI_Gate::TRIG_OUTPUT + 6)); - addOutput(createOutput(mm2px(Vec(38.693932, 84.945023)), module, MIDI_Gate::TRIG_OUTPUT + 7)); - addOutput(createOutput(mm2px(Vec(3.8943343, 96.543976)), module, MIDI_Gate::TRIG_OUTPUT + 8)); - addOutput(createOutput(mm2px(Vec(15.494659, 96.543976)), module, MIDI_Gate::TRIG_OUTPUT + 9)); - addOutput(createOutput(mm2px(Vec(27.09498, 96.543976)), module, MIDI_Gate::TRIG_OUTPUT + 10)); - addOutput(createOutput(mm2px(Vec(38.693932, 96.543976)), module, MIDI_Gate::TRIG_OUTPUT + 11)); - addOutput(createOutput(mm2px(Vec(3.894335, 108.14429)), module, MIDI_Gate::TRIG_OUTPUT + 12)); - addOutput(createOutput(mm2px(Vec(15.49466, 108.14429)), module, MIDI_Gate::TRIG_OUTPUT + 13)); - addOutput(createOutput(mm2px(Vec(27.09498, 108.14429)), module, MIDI_Gate::TRIG_OUTPUT + 14)); - addOutput(createOutput(mm2px(Vec(38.693932, 108.14429)), module, MIDI_Gate::TRIG_OUTPUT + 15)); + addOutput(createOutput(mm2px(Vec(3.894335, 73.344704)), module, MIDI_Gate::GATE_OUTPUTS + 0)); + addOutput(createOutput(mm2px(Vec(15.494659, 73.344704)), module, MIDI_Gate::GATE_OUTPUTS + 1)); + addOutput(createOutput(mm2px(Vec(27.094982, 73.344704)), module, MIDI_Gate::GATE_OUTPUTS + 2)); + addOutput(createOutput(mm2px(Vec(38.693932, 73.344704)), module, MIDI_Gate::GATE_OUTPUTS + 3)); + addOutput(createOutput(mm2px(Vec(3.8943355, 84.945023)), module, MIDI_Gate::GATE_OUTPUTS + 4)); + addOutput(createOutput(mm2px(Vec(15.49466, 84.945023)), module, MIDI_Gate::GATE_OUTPUTS + 5)); + addOutput(createOutput(mm2px(Vec(27.094982, 84.945023)), module, MIDI_Gate::GATE_OUTPUTS + 6)); + addOutput(createOutput(mm2px(Vec(38.693932, 84.945023)), module, MIDI_Gate::GATE_OUTPUTS + 7)); + addOutput(createOutput(mm2px(Vec(3.8943343, 96.543976)), module, MIDI_Gate::GATE_OUTPUTS + 8)); + addOutput(createOutput(mm2px(Vec(15.494659, 96.543976)), module, MIDI_Gate::GATE_OUTPUTS + 9)); + addOutput(createOutput(mm2px(Vec(27.09498, 96.543976)), module, MIDI_Gate::GATE_OUTPUTS + 10)); + addOutput(createOutput(mm2px(Vec(38.693932, 96.543976)), module, MIDI_Gate::GATE_OUTPUTS + 11)); + addOutput(createOutput(mm2px(Vec(3.894335, 108.14429)), module, MIDI_Gate::GATE_OUTPUTS + 12)); + addOutput(createOutput(mm2px(Vec(15.49466, 108.14429)), module, MIDI_Gate::GATE_OUTPUTS + 13)); + addOutput(createOutput(mm2px(Vec(27.09498, 108.14429)), module, MIDI_Gate::GATE_OUTPUTS + 14)); + addOutput(createOutput(mm2px(Vec(38.693932, 108.14429)), module, MIDI_Gate::GATE_OUTPUTS + 15)); typedef Grid16MidiWidget> TMidiWidget; TMidiWidget* midiWidget = createWidget(mm2px(Vec(3.399621, 14.837339))); @@ -243,18 +221,36 @@ struct MIDI_GateWidget : ModuleWidget { void appendContextMenu(Menu* menu) override { MIDI_Gate* module = dynamic_cast(this->module); + struct VelocityItem : MenuItem { + MIDI_Gate* module; + void onAction(const ActionEvent& e) override { + module->velocityMode ^= true; + } + }; menu->addChild(new MenuSeparator); - MIDI_GateVelocityItem* velocityItem = createMenuItem("Velocity mode", CHECKMARK(module->velocityMode)); + VelocityItem* velocityItem = createMenuItem("Velocity mode", CHECKMARK(module->velocityMode)); velocityItem->module = module; menu->addChild(velocityItem); - MIDI_GateMpeModeItem* mpeModeItem = new MIDI_GateMpeModeItem; + struct MpeModeItem : MenuItem { + MIDI_Gate* module; + void onAction(const ActionEvent& e) override { + module->mpeMode ^= true; + } + }; + MpeModeItem* mpeModeItem = new MpeModeItem; mpeModeItem->text = "MPE mode"; mpeModeItem->rightText = CHECKMARK(module->mpeMode); mpeModeItem->module = module; menu->addChild(mpeModeItem); - MIDI_GatePanicItem* panicItem = new MIDI_GatePanicItem; + struct PanicItem : MenuItem { + MIDI_Gate* module; + void onAction(const ActionEvent& e) override { + module->panic(); + } + }; + PanicItem* panicItem = new PanicItem; panicItem->text = "Panic"; panicItem->module = module; menu->addChild(panicItem);