Browse Source

Clean up MIDI-CV, CC, and Gate.

tags/v2.0.0
Andrew Belt 3 years ago
parent
commit
898bc44794
4 changed files with 162 additions and 128 deletions
  1. +61
    -6
      include/componentlibrary.hpp
  2. +17
    -18
      src/core/MIDI_CC.cpp
  3. +33
    -49
      src/core/MIDI_CV.cpp
  4. +51
    -55
      src/core/MIDI_Gate.cpp

+ 61
- 6
include/componentlibrary.hpp View File

@@ -302,179 +302,234 @@ struct Davies1900hLargeRedKnob : Davies1900hKnob {




struct Rogan : app::SvgKnob { struct Rogan : app::SvgKnob {
widget::SvgWidget* bg;
widget::SvgWidget* fg;

Rogan() { Rogan() {
minAngle = -0.83 * M_PI; minAngle = -0.83 * M_PI;
maxAngle = 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 { struct Rogan6PSWhite : Rogan {
Rogan6PSWhite() { Rogan6PSWhite() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan6PSWhite.svg"))); 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 { struct Rogan5PSGray : Rogan {
Rogan5PSGray() { Rogan5PSGray() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan5PSGray.svg"))); 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 { struct Rogan3PSBlue : Rogan {
Rogan3PSBlue() { Rogan3PSBlue() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSBlue.svg"))); 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 { struct Rogan3PSRed : Rogan {
Rogan3PSRed() { Rogan3PSRed() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSRed.svg"))); 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 { struct Rogan3PSGreen : Rogan {
Rogan3PSGreen() { Rogan3PSGreen() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSGreen.svg"))); 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 { struct Rogan3PSWhite : Rogan {
Rogan3PSWhite() { Rogan3PSWhite() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite.svg"))); 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"))); 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"))); fg->setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PSWhite-fg.svg")));
fb->addChildAbove(fg, tw);
} }
}; };


struct Rogan3PBlue : Rogan { struct Rogan3PBlue : Rogan {
Rogan3PBlue() { Rogan3PBlue() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PBlue.svg"))); 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 { struct Rogan3PRed : Rogan {
Rogan3PRed() { Rogan3PRed() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PRed.svg"))); 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 { struct Rogan3PGreen : Rogan {
Rogan3PGreen() { Rogan3PGreen() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PGreen.svg"))); 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 { struct Rogan3PWhite : Rogan {
Rogan3PWhite() { Rogan3PWhite() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan3PWhite.svg"))); 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 { struct Rogan2SGray : Rogan {
Rogan2SGray() { Rogan2SGray() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2SGray.svg"))); 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 { struct Rogan2PSBlue : Rogan {
Rogan2PSBlue() { Rogan2PSBlue() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PSBlue.svg"))); 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 { struct Rogan2PSRed : Rogan {
Rogan2PSRed() { Rogan2PSRed() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PSRed.svg"))); 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 { struct Rogan2PSGreen : Rogan {
Rogan2PSGreen() { Rogan2PSGreen() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PSGreen.svg"))); 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 { struct Rogan2PSWhite : Rogan {
Rogan2PSWhite() { Rogan2PSWhite() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PSWhite.svg"))); 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 { struct Rogan2PBlue : Rogan {
Rogan2PBlue() { Rogan2PBlue() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PBlue.svg"))); 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 { struct Rogan2PRed : Rogan {
Rogan2PRed() { Rogan2PRed() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PRed.svg"))); 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 { struct Rogan2PGreen : Rogan {
Rogan2PGreen() { Rogan2PGreen() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PGreen.svg"))); 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 { struct Rogan2PWhite : Rogan {
Rogan2PWhite() { Rogan2PWhite() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan2PWhite.svg"))); 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 { struct Rogan1PSBlue : Rogan {
Rogan1PSBlue() { Rogan1PSBlue() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PSBlue.svg"))); 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 { struct Rogan1PSRed : Rogan {
Rogan1PSRed() { Rogan1PSRed() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PSRed.svg"))); 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 { struct Rogan1PSGreen : Rogan {
Rogan1PSGreen() { Rogan1PSGreen() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PSGreen.svg"))); 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 { struct Rogan1PSWhite : Rogan {
Rogan1PSWhite() { Rogan1PSWhite() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PSWhite.svg"))); 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 { struct Rogan1PBlue : Rogan {
Rogan1PBlue() { Rogan1PBlue() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PBlue.svg"))); 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 { struct Rogan1PRed : Rogan {
Rogan1PRed() { Rogan1PRed() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PRed.svg"))); 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 { struct Rogan1PGreen : Rogan {
Rogan1PGreen() { Rogan1PGreen() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PGreen.svg"))); 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 { struct Rogan1PWhite : Rogan {
Rogan1PWhite() { Rogan1PWhite() {
setSvg(Svg::load(asset::system("res/ComponentLibrary/Rogan1PWhite.svg"))); 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")));
} }
}; };




+ 17
- 18
src/core/MIDI_CC.cpp View File

@@ -21,6 +21,7 @@ struct MIDI_CC : Module {
}; };


midi::InputQueue midiInput; midi::InputQueue midiInput;

/** [cc][channel] */ /** [cc][channel] */
int8_t ccValues[128][16]; int8_t ccValues[128][16];
/** When LSB is enabled for CC 0-31, the MSB is stored here until the LSB is received. /** 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]; dsp::ExponentialFilter valueFilters[16][16];
bool smooth; bool smooth;
bool mpeMode; bool mpeMode;
bool lsbEnabled;
bool lsbMode;


MIDI_CC() { MIDI_CC() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
@@ -66,7 +67,7 @@ struct MIDI_CC : Module {
midiInput.reset(); midiInput.reset();
smooth = true; smooth = true;
mpeMode = false; mpeMode = false;
lsbEnabled = false;
lsbMode = false;
} }


void process(const ProcessArgs& args) override { void process(const ProcessArgs& args) override {
@@ -80,6 +81,7 @@ struct MIDI_CC : Module {
} }


int channels = mpeMode ? 16 : 1; int channels = mpeMode ? 16 : 1;

for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (!outputs[CC_OUTPUT + i].isConnected()) if (!outputs[CC_OUTPUT + i].isConnected())
continue; continue;
@@ -89,7 +91,7 @@ struct MIDI_CC : Module {


for (int c = 0; c < channels; c++) { for (int c = 0; c < channels; c++) {
int16_t cellValue = int16_t(ccValues[cc][c]) * 128; int16_t cellValue = int16_t(ccValues[cc][c]) * 128;
if (lsbEnabled && cc < 32)
if (lsbMode && cc < 32)
cellValue += ccValues[cc + 32][c]; 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. // 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); float value = float(cellValue) / (128 * 127);
@@ -135,11 +137,11 @@ struct MIDI_CC : Module {
learningId = -1; learningId = -1;
} }


if (lsbEnabled && cc < 32) {
if (lsbMode && cc < 32) {
// Don't set MSB yet. Wait for LSB to be received. // Don't set MSB yet. Wait for LSB to be received.
msbValues[cc][c] = value; msbValues[cc][c] = value;
} }
else if (lsbEnabled && 32 <= cc && cc < 64) {
else if (lsbMode && 32 <= cc && cc < 64) {
// Apply MSB when LSB is received // Apply MSB when LSB is received
ccValues[cc - 32][c] = msbValues[cc - 32][c]; ccValues[cc - 32][c] = msbValues[cc - 32][c];
ccValues[cc][c] = value; 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, "smooth", json_boolean(smooth));
json_object_set_new(rootJ, "mpeMode", json_boolean(mpeMode)); 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; return rootJ;
} }


@@ -206,9 +208,9 @@ struct MIDI_CC : Module {
if (mpeModeJ) if (mpeModeJ)
mpeMode = json_boolean_value(mpeModeJ); mpeMode = json_boolean_value(mpeModeJ);


json_t* lsbEnabledJ = json_object_get(rootJ, "lsbEnabled");
json_t* lsbEnabledJ = json_object_get(rootJ, "lsbMode");
if (lsbEnabledJ) if (lsbEnabledJ)
lsbEnabled = json_boolean_value(lsbEnabledJ);
lsbMode = json_boolean_value(lsbEnabledJ);
} }
}; };


@@ -259,7 +261,6 @@ struct MIDI_CCWidget : ModuleWidget {
module->smooth ^= true; module->smooth ^= true;
} }
}; };

SmoothItem* smoothItem = new SmoothItem; SmoothItem* smoothItem = new SmoothItem;
smoothItem->text = "Smooth CC"; smoothItem->text = "Smooth CC";
smoothItem->rightText = CHECKMARK(module->smooth); smoothItem->rightText = CHECKMARK(module->smooth);
@@ -272,25 +273,23 @@ struct MIDI_CCWidget : ModuleWidget {
module->mpeMode ^= true; module->mpeMode ^= true;
} }
}; };

MpeModeItem* mpeModeItem = new MpeModeItem; MpeModeItem* mpeModeItem = new MpeModeItem;
mpeModeItem->text = "MPE mode"; mpeModeItem->text = "MPE mode";
mpeModeItem->rightText = CHECKMARK(module->mpeMode); mpeModeItem->rightText = CHECKMARK(module->mpeMode);
mpeModeItem->module = module; mpeModeItem->module = module;
menu->addChild(mpeModeItem); menu->addChild(mpeModeItem);


struct LSBItem : MenuItem {
struct LsbModeItem : MenuItem {
MIDI_CC* module; MIDI_CC* module;
void onAction(const ActionEvent& e) override { 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);
} }
}; };




+ 33
- 49
src/core/MIDI_CV.cpp View File

@@ -15,11 +15,11 @@ struct MIDI_CV : Module {
NUM_INPUTS NUM_INPUTS
}; };
enum OutputIds { enum OutputIds {
CV_OUTPUT,
PITCH_OUTPUT,
GATE_OUTPUT, GATE_OUTPUT,
VELOCITY_OUTPUT, VELOCITY_OUTPUT,
AFTERTOUCH_OUTPUT, AFTERTOUCH_OUTPUT,
PITCH_OUTPUT,
PW_OUTPUT,
MOD_OUTPUT, MOD_OUTPUT,
RETRIGGER_OUTPUT, RETRIGGER_OUTPUT,
CLOCK_OUTPUT, CLOCK_OUTPUT,
@@ -59,10 +59,14 @@ struct MIDI_CV : Module {


int rotateIndex; 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]; uint8_t mods[16];
dsp::ExponentialFilter pitchFilters[16];
dsp::ExponentialFilter pwFilters[16];
dsp::ExponentialFilter modFilters[16]; dsp::ExponentialFilter modFilters[16];


dsp::PulseGenerator clockPulse; dsp::PulseGenerator clockPulse;
@@ -74,11 +78,11 @@ struct MIDI_CV : Module {


MIDI_CV() { MIDI_CV() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); 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(GATE_OUTPUT, "Gate");
configOutput(VELOCITY_OUTPUT, "Velocity"); configOutput(VELOCITY_OUTPUT, "Velocity");
configOutput(AFTERTOUCH_OUTPUT, "Aftertouch"); configOutput(AFTERTOUCH_OUTPUT, "Aftertouch");
configOutput(PITCH_OUTPUT, "Pitch wheel");
configOutput(PW_OUTPUT, "Pitch wheel");
configOutput(MOD_OUTPUT, "Mod wheel"); configOutput(MOD_OUTPUT, "Mod wheel");
configOutput(RETRIGGER_OUTPUT, "Retrigger"); configOutput(RETRIGGER_OUTPUT, "Retrigger");
configOutput(CLOCK_OUTPUT, "Clock"); configOutput(CLOCK_OUTPUT, "Clock");
@@ -88,7 +92,7 @@ struct MIDI_CV : Module {
configOutput(CONTINUE_OUTPUT, "Continue"); configOutput(CONTINUE_OUTPUT, "Continue");
heldNotes.reserve(128); heldNotes.reserve(128);
for (int c = 0; c < 16; c++) { 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); modFilters[c].setTau(1 / 30.f);
} }
onReset(); onReset();
@@ -110,9 +114,9 @@ struct MIDI_CV : Module {
gates[c] = false; gates[c] = false;
velocities[c] = 0; velocities[c] = 0;
aftertouches[c] = 0; aftertouches[c] = 0;
pitches[c] = 8192;
pws[c] = 8192;
mods[c] = 0; mods[c] = 0;
pitchFilters[c].reset();
pwFilters[c].reset();
modFilters[c].reset(); modFilters[c].reset();
} }
pedal = false; pedal = false;
@@ -130,13 +134,13 @@ struct MIDI_CV : Module {
midiInput.queue.pop(); midiInput.queue.pop();
} }


outputs[CV_OUTPUT].setChannels(channels);
outputs[PITCH_OUTPUT].setChannels(channels);
outputs[GATE_OUTPUT].setChannels(channels); outputs[GATE_OUTPUT].setChannels(channels);
outputs[VELOCITY_OUTPUT].setChannels(channels); outputs[VELOCITY_OUTPUT].setChannels(channels);
outputs[AFTERTOUCH_OUTPUT].setChannels(channels); outputs[AFTERTOUCH_OUTPUT].setChannels(channels);
outputs[RETRIGGER_OUTPUT].setChannels(channels); outputs[RETRIGGER_OUTPUT].setChannels(channels);
for (int c = 0; c < channels; c++) { 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[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[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); 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 // 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) if (smooth)
pitch = pitchFilters[c].process(args.sampleTime, pitch);
pw = pwFilters[c].process(args.sampleTime, pw);
else 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; float mod = mods[c] / 127.f;
mod = clamp(mod, 0.f, 1.f); mod = clamp(mod, 0.f, 1.f);
if (smooth) if (smooth)
modFilters[c].process(args.sampleTime, mod);
mod = modFilters[c].process(args.sampleTime, mod);
else else
modFilters[c].out = mod; 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); outputs[CLOCK_OUTPUT].setVoltage(clockPulse.process(args.sampleTime) ? 10.f : 0.f);
@@ -233,7 +225,7 @@ struct MIDI_CV : Module {
// pitch wheel // pitch wheel
case 0xe: { case 0xe: {
int c = (polyMode == MPE_MODE) ? msg.getChannel() : 0; 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; } break;
case 0xf: { case 0xf: {
processSystem(msg); processSystem(msg);
@@ -440,7 +432,7 @@ struct MIDI_CV : Module {
json_object_set_new(rootJ, "clockDivision", json_integer(clockDivision)); json_object_set_new(rootJ, "clockDivision", json_integer(clockDivision));
// Saving/restoring pitch and mod doesn't make much sense for MPE. // Saving/restoring pitch and mod doesn't make much sense for MPE.
if (polyMode != MPE_MODE) { 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, "lastMod", json_integer(mods[0]));
} }
json_object_set_new(rootJ, "midi", midiInput.toJson()); json_object_set_new(rootJ, "midi", midiInput.toJson());
@@ -466,7 +458,7 @@ struct MIDI_CV : Module {


json_t* lastPitchJ = json_object_get(rootJ, "lastPitch"); json_t* lastPitchJ = json_object_get(rootJ, "lastPitch");
if (lastPitchJ) if (lastPitchJ)
pitches[0] = json_integer_value(lastPitchJ);
pws[0] = json_integer_value(lastPitchJ);


json_t* lastModJ = json_object_get(rootJ, "lastMod"); json_t* lastModJ = json_object_get(rootJ, "lastMod");
if (lastModJ) if (lastModJ)
@@ -489,11 +481,11 @@ struct MIDI_CVWidget : ModuleWidget {
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); 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))); addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));


addOutput(createOutput<PJ301MPort>(mm2px(Vec(4.61505, 60.1445)), module, MIDI_CV::CV_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(4.61505, 60.1445)), module, MIDI_CV::PITCH_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(16.214, 60.1445)), module, MIDI_CV::GATE_OUTPUT)); addOutput(createOutput<PJ301MPort>(mm2px(Vec(16.214, 60.1445)), module, MIDI_CV::GATE_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.8143, 60.1445)), module, MIDI_CV::VELOCITY_OUTPUT)); addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.8143, 60.1445)), module, MIDI_CV::VELOCITY_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(4.61505, 76.1449)), module, MIDI_CV::AFTERTOUCH_OUTPUT)); addOutput(createOutput<PJ301MPort>(mm2px(Vec(4.61505, 76.1449)), module, MIDI_CV::AFTERTOUCH_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(16.214, 76.1449)), module, MIDI_CV::PITCH_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(16.214, 76.1449)), module, MIDI_CV::PW_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.8143, 76.1449)), module, MIDI_CV::MOD_OUTPUT)); addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.8143, 76.1449)), module, MIDI_CV::MOD_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(4.61505, 92.1439)), module, MIDI_CV::CLOCK_OUTPUT)); addOutput(createOutput<PJ301MPort>(mm2px(Vec(4.61505, 92.1439)), module, MIDI_CV::CLOCK_OUTPUT));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(16.214, 92.1439)), module, MIDI_CV::CLOCK_DIV_OUTPUT)); addOutput(createOutput<PJ301MPort>(mm2px(Vec(16.214, 92.1439)), module, MIDI_CV::CLOCK_DIV_OUTPUT));
@@ -519,7 +511,6 @@ struct MIDI_CVWidget : ModuleWidget {
module->smooth ^= true; module->smooth ^= true;
} }
}; };

SmoothItem* smoothItem = new SmoothItem; SmoothItem* smoothItem = new SmoothItem;
smoothItem->text = "Smooth pitch/mod wheel"; smoothItem->text = "Smooth pitch/mod wheel";
smoothItem->rightText = CHECKMARK(module->smooth); smoothItem->rightText = CHECKMARK(module->smooth);
@@ -533,7 +524,6 @@ struct MIDI_CVWidget : ModuleWidget {
module->clockDivision = clockDivision; module->clockDivision = clockDivision;
} }
}; };

struct ClockDivisionItem : MenuItem { struct ClockDivisionItem : MenuItem {
MIDI_CV* module; MIDI_CV* module;
Menu* createChildMenu() override { Menu* createChildMenu() override {
@@ -551,7 +541,6 @@ struct MIDI_CVWidget : ModuleWidget {
return menu; return menu;
} }
}; };

ClockDivisionItem* clockDivisionItem = new ClockDivisionItem; ClockDivisionItem* clockDivisionItem = new ClockDivisionItem;
clockDivisionItem->text = "CLK/N divider"; clockDivisionItem->text = "CLK/N divider";
clockDivisionItem->rightText = RIGHT_ARROW; clockDivisionItem->rightText = RIGHT_ARROW;
@@ -565,7 +554,6 @@ struct MIDI_CVWidget : ModuleWidget {
module->setChannels(channels); module->setChannels(channels);
} }
}; };

struct ChannelItem : MenuItem { struct ChannelItem : MenuItem {
MIDI_CV* module; MIDI_CV* module;
Menu* createChildMenu() override { Menu* createChildMenu() override {
@@ -584,7 +572,6 @@ struct MIDI_CVWidget : ModuleWidget {
return menu; return menu;
} }
}; };

ChannelItem* channelItem = new ChannelItem; ChannelItem* channelItem = new ChannelItem;
channelItem->text = "Polyphony channels"; channelItem->text = "Polyphony channels";
channelItem->rightText = string::f("%d", module->channels) + " " + RIGHT_ARROW; channelItem->rightText = string::f("%d", module->channels) + " " + RIGHT_ARROW;
@@ -598,7 +585,6 @@ struct MIDI_CVWidget : ModuleWidget {
module->setPolyMode(polyMode); module->setPolyMode(polyMode);
} }
}; };

struct PolyModeItem : MenuItem { struct PolyModeItem : MenuItem {
MIDI_CV* module; MIDI_CV* module;
Menu* createChildMenu() override { Menu* createChildMenu() override {
@@ -621,7 +607,6 @@ struct MIDI_CVWidget : ModuleWidget {
return menu; return menu;
} }
}; };

PolyModeItem* polyModeItem = new PolyModeItem; PolyModeItem* polyModeItem = new PolyModeItem;
polyModeItem->text = "Polyphony mode"; polyModeItem->text = "Polyphony mode";
polyModeItem->rightText = RIGHT_ARROW; polyModeItem->rightText = RIGHT_ARROW;
@@ -634,7 +619,6 @@ struct MIDI_CVWidget : ModuleWidget {
module->panic(); module->panic();
} }
}; };

PanicItem* panicItem = new PanicItem; PanicItem* panicItem = new PanicItem;
panicItem->text = "Panic"; panicItem->text = "Panic";
panicItem->module = module; panicItem->module = module;


+ 51
- 55
src/core/MIDI_Gate.cpp View File

@@ -13,7 +13,7 @@ struct MIDI_Gate : Module {
NUM_INPUTS NUM_INPUTS
}; };
enum OutputIds { enum OutputIds {
ENUMS(TRIG_OUTPUT, 16),
ENUMS(GATE_OUTPUTS, 16),
NUM_OUTPUTS NUM_OUTPUTS
}; };
enum LightIds { enum LightIds {
@@ -22,21 +22,23 @@ struct MIDI_Gate : Module {


midi::InputQueue midiInput; midi::InputQueue midiInput;


/** [cell][c] */
/** [cell][channel] */
bool gates[16][16]; bool gates[16][16];
/** [cell][c] */
/** [cell][channel] */
float gateTimes[16][16]; float gateTimes[16][16];
/** [cell][c] */
/** [cell][channel] */
uint8_t velocities[16][16]; 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() { MIDI_Gate() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
for (int i = 0; i < 16; i++) 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(); onReset();
} }
@@ -76,16 +78,16 @@ struct MIDI_Gate : Module {
int channels = mpeMode ? 16 : 1; int channels = mpeMode ? 16 : 1;


for (int i = 0; i < 16; i++) { 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++) { for (int c = 0; c < channels; c++) {
// Make sure all pulses last longer than 1ms // Make sure all pulses last longer than 1ms
if (gates[i][c] || gateTimes[i][c] > 0.f) { if (gates[i][c] || gateTimes[i][c] > 0.f) {
float velocity = velocityMode ? (velocities[i][c] / 127.f) : 1.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; gateTimes[i][c] -= args.sampleTime;
} }
else { 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 { struct MIDI_GateWidget : ModuleWidget {
MIDI_GateWidget(MIDI_Gate* module) { MIDI_GateWidget(MIDI_Gate* module) {
setModule(module); setModule(module);
@@ -215,22 +193,22 @@ struct MIDI_GateWidget : ModuleWidget {
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); 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))); addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));


addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.894335, 73.344704)), module, MIDI_Gate::TRIG_OUTPUT + 0));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.494659, 73.344704)), module, MIDI_Gate::TRIG_OUTPUT + 1));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.094982, 73.344704)), module, MIDI_Gate::TRIG_OUTPUT + 2));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(38.693932, 73.344704)), module, MIDI_Gate::TRIG_OUTPUT + 3));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.8943355, 84.945023)), module, MIDI_Gate::TRIG_OUTPUT + 4));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.49466, 84.945023)), module, MIDI_Gate::TRIG_OUTPUT + 5));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.094982, 84.945023)), module, MIDI_Gate::TRIG_OUTPUT + 6));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(38.693932, 84.945023)), module, MIDI_Gate::TRIG_OUTPUT + 7));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.8943343, 96.543976)), module, MIDI_Gate::TRIG_OUTPUT + 8));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.494659, 96.543976)), module, MIDI_Gate::TRIG_OUTPUT + 9));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.09498, 96.543976)), module, MIDI_Gate::TRIG_OUTPUT + 10));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(38.693932, 96.543976)), module, MIDI_Gate::TRIG_OUTPUT + 11));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.894335, 108.14429)), module, MIDI_Gate::TRIG_OUTPUT + 12));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.49466, 108.14429)), module, MIDI_Gate::TRIG_OUTPUT + 13));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.09498, 108.14429)), module, MIDI_Gate::TRIG_OUTPUT + 14));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(38.693932, 108.14429)), module, MIDI_Gate::TRIG_OUTPUT + 15));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.894335, 73.344704)), module, MIDI_Gate::GATE_OUTPUTS + 0));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.494659, 73.344704)), module, MIDI_Gate::GATE_OUTPUTS + 1));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.094982, 73.344704)), module, MIDI_Gate::GATE_OUTPUTS + 2));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(38.693932, 73.344704)), module, MIDI_Gate::GATE_OUTPUTS + 3));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.8943355, 84.945023)), module, MIDI_Gate::GATE_OUTPUTS + 4));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.49466, 84.945023)), module, MIDI_Gate::GATE_OUTPUTS + 5));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.094982, 84.945023)), module, MIDI_Gate::GATE_OUTPUTS + 6));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(38.693932, 84.945023)), module, MIDI_Gate::GATE_OUTPUTS + 7));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.8943343, 96.543976)), module, MIDI_Gate::GATE_OUTPUTS + 8));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.494659, 96.543976)), module, MIDI_Gate::GATE_OUTPUTS + 9));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.09498, 96.543976)), module, MIDI_Gate::GATE_OUTPUTS + 10));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(38.693932, 96.543976)), module, MIDI_Gate::GATE_OUTPUTS + 11));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.894335, 108.14429)), module, MIDI_Gate::GATE_OUTPUTS + 12));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.49466, 108.14429)), module, MIDI_Gate::GATE_OUTPUTS + 13));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.09498, 108.14429)), module, MIDI_Gate::GATE_OUTPUTS + 14));
addOutput(createOutput<PJ301MPort>(mm2px(Vec(38.693932, 108.14429)), module, MIDI_Gate::GATE_OUTPUTS + 15));


typedef Grid16MidiWidget<NoteChoice<MIDI_Gate>> TMidiWidget; typedef Grid16MidiWidget<NoteChoice<MIDI_Gate>> TMidiWidget;
TMidiWidget* midiWidget = createWidget<TMidiWidget>(mm2px(Vec(3.399621, 14.837339))); TMidiWidget* midiWidget = createWidget<TMidiWidget>(mm2px(Vec(3.399621, 14.837339)));
@@ -243,18 +221,36 @@ struct MIDI_GateWidget : ModuleWidget {
void appendContextMenu(Menu* menu) override { void appendContextMenu(Menu* menu) override {
MIDI_Gate* module = dynamic_cast<MIDI_Gate*>(this->module); MIDI_Gate* module = dynamic_cast<MIDI_Gate*>(this->module);


struct VelocityItem : MenuItem {
MIDI_Gate* module;
void onAction(const ActionEvent& e) override {
module->velocityMode ^= true;
}
};
menu->addChild(new MenuSeparator); menu->addChild(new MenuSeparator);
MIDI_GateVelocityItem* velocityItem = createMenuItem<MIDI_GateVelocityItem>("Velocity mode", CHECKMARK(module->velocityMode));
VelocityItem* velocityItem = createMenuItem<VelocityItem>("Velocity mode", CHECKMARK(module->velocityMode));
velocityItem->module = module; velocityItem->module = module;
menu->addChild(velocityItem); 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->text = "MPE mode";
mpeModeItem->rightText = CHECKMARK(module->mpeMode); mpeModeItem->rightText = CHECKMARK(module->mpeMode);
mpeModeItem->module = module; mpeModeItem->module = module;
menu->addChild(mpeModeItem); 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->text = "Panic";
panicItem->module = module; panicItem->module = module;
menu->addChild(panicItem); menu->addChild(panicItem);


Loading…
Cancel
Save