|
@@ -39,11 +39,12 @@ struct MIDIToCVInterface : Module { |
|
|
uint16_t pitch = 0; |
|
|
uint16_t pitch = 0; |
|
|
ExponentialFilter pitchFilter; |
|
|
ExponentialFilter pitchFilter; |
|
|
PulseGenerator retriggerPulse; |
|
|
PulseGenerator retriggerPulse; |
|
|
PulseGenerator clock1Pulse; |
|
|
|
|
|
PulseGenerator clock2Pulse; |
|
|
|
|
|
|
|
|
PulseGenerator clockPulses[2]; |
|
|
PulseGenerator startPulse; |
|
|
PulseGenerator startPulse; |
|
|
PulseGenerator stopPulse; |
|
|
PulseGenerator stopPulse; |
|
|
PulseGenerator continuePulse; |
|
|
PulseGenerator continuePulse; |
|
|
|
|
|
int clock = 0; |
|
|
|
|
|
int divisions[2]; |
|
|
|
|
|
|
|
|
struct NoteData { |
|
|
struct NoteData { |
|
|
uint8_t velocity = 0; |
|
|
uint8_t velocity = 0; |
|
@@ -62,11 +63,28 @@ struct MIDIToCVInterface : Module { |
|
|
|
|
|
|
|
|
json_t *toJson() override { |
|
|
json_t *toJson() override { |
|
|
json_t *rootJ = json_object(); |
|
|
json_t *rootJ = json_object(); |
|
|
|
|
|
|
|
|
|
|
|
json_t *divisionsJ = json_array(); |
|
|
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
|
|
json_t *divisionJ = json_integer(divisions[i]); |
|
|
|
|
|
json_array_append_new(divisionsJ, divisionJ); |
|
|
|
|
|
} |
|
|
|
|
|
json_object_set_new(rootJ, "divisions", divisionsJ); |
|
|
|
|
|
|
|
|
json_object_set_new(rootJ, "midi", midiInput.toJson()); |
|
|
json_object_set_new(rootJ, "midi", midiInput.toJson()); |
|
|
return rootJ; |
|
|
return rootJ; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void fromJson(json_t *rootJ) override { |
|
|
void fromJson(json_t *rootJ) override { |
|
|
|
|
|
json_t *divisionsJ = json_object_get(rootJ, "divisions"); |
|
|
|
|
|
if (divisionsJ) { |
|
|
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
|
|
json_t *divisionJ = json_array_get(divisionsJ, i); |
|
|
|
|
|
if (divisionJ) |
|
|
|
|
|
divisions[i] = json_integer_value(divisionJ); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
json_t *midiJ = json_object_get(rootJ, "midi"); |
|
|
json_t *midiJ = json_object_get(rootJ, "midi"); |
|
|
if (midiJ) |
|
|
if (midiJ) |
|
|
midiInput.fromJson(midiJ); |
|
|
midiInput.fromJson(midiJ); |
|
@@ -77,6 +95,9 @@ struct MIDIToCVInterface : Module { |
|
|
lastNote = 60; |
|
|
lastNote = 60; |
|
|
pedal = false; |
|
|
pedal = false; |
|
|
gate = false; |
|
|
gate = false; |
|
|
|
|
|
clock = 0; |
|
|
|
|
|
divisions[0] = 24; |
|
|
|
|
|
divisions[1] = 6; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void pressNote(uint8_t note) { |
|
|
void pressNote(uint8_t note) { |
|
@@ -137,8 +158,8 @@ struct MIDIToCVInterface : Module { |
|
|
outputs[MOD_OUTPUT].value = modFilter.process(rescale(mod, 0, 127, 0.f, 10.f)); |
|
|
outputs[MOD_OUTPUT].value = modFilter.process(rescale(mod, 0, 127, 0.f, 10.f)); |
|
|
|
|
|
|
|
|
outputs[RETRIGGER_OUTPUT].value = retriggerPulse.process(deltaTime) ? 10.f : 0.f; |
|
|
outputs[RETRIGGER_OUTPUT].value = retriggerPulse.process(deltaTime) ? 10.f : 0.f; |
|
|
outputs[CLOCK_1_OUTPUT].value = clock1Pulse.process(deltaTime) ? 10.f : 0.f; |
|
|
|
|
|
outputs[CLOCK_2_OUTPUT].value = clock2Pulse.process(deltaTime) ? 10.f : 0.f; |
|
|
|
|
|
|
|
|
outputs[CLOCK_1_OUTPUT].value = clockPulses[0].process(deltaTime) ? 10.f : 0.f; |
|
|
|
|
|
outputs[CLOCK_2_OUTPUT].value = clockPulses[1].process(deltaTime) ? 10.f : 0.f; |
|
|
|
|
|
|
|
|
outputs[START_OUTPUT].value = startPulse.process(deltaTime) ? 10.f : 0.f; |
|
|
outputs[START_OUTPUT].value = startPulse.process(deltaTime) ? 10.f : 0.f; |
|
|
outputs[STOP_OUTPUT].value = stopPulse.process(deltaTime) ? 10.f : 0.f; |
|
|
outputs[STOP_OUTPUT].value = stopPulse.process(deltaTime) ? 10.f : 0.f; |
|
@@ -205,11 +226,20 @@ struct MIDIToCVInterface : Module { |
|
|
switch (msg.channel()) { |
|
|
switch (msg.channel()) { |
|
|
// Timing |
|
|
// Timing |
|
|
case 0x8: { |
|
|
case 0x8: { |
|
|
// TODO |
|
|
|
|
|
|
|
|
if (clock % divisions[0] == 0) { |
|
|
|
|
|
clockPulses[0].trigger(1e-3); |
|
|
|
|
|
} |
|
|
|
|
|
if (clock % divisions[1] == 0) { |
|
|
|
|
|
clockPulses[1].trigger(1e-3); |
|
|
|
|
|
} |
|
|
|
|
|
if (++clock >= (24*16*16)) { |
|
|
|
|
|
clock = 0; |
|
|
|
|
|
} |
|
|
} break; |
|
|
} break; |
|
|
// Start |
|
|
// Start |
|
|
case 0xa: { |
|
|
case 0xa: { |
|
|
startPulse.trigger(1e-3); |
|
|
startPulse.trigger(1e-3); |
|
|
|
|
|
clock = 0; |
|
|
} break; |
|
|
} break; |
|
|
// Continue |
|
|
// Continue |
|
|
case 0xb: { |
|
|
case 0xb: { |
|
@@ -252,6 +282,45 @@ struct MIDIToCVInterfaceWidget : ModuleWidget { |
|
|
midiWidget->midiIO = &module->midiInput; |
|
|
midiWidget->midiIO = &module->midiInput; |
|
|
addChild(midiWidget); |
|
|
addChild(midiWidget); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void appendContextMenu(Menu *menu) override { |
|
|
|
|
|
MIDIToCVInterface *module = dynamic_cast<MIDIToCVInterface*>(this->module); |
|
|
|
|
|
|
|
|
|
|
|
struct ClockDivisionItem : MenuItem { |
|
|
|
|
|
MIDIToCVInterface *module; |
|
|
|
|
|
int index; |
|
|
|
|
|
int division; |
|
|
|
|
|
void onAction(EventAction &e) override { |
|
|
|
|
|
module->divisions[index] = division; |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct ClockItem : MenuItem { |
|
|
|
|
|
MIDIToCVInterface *module; |
|
|
|
|
|
int index; |
|
|
|
|
|
Menu *createChildMenu() override { |
|
|
|
|
|
Menu *menu = new Menu(); |
|
|
|
|
|
std::vector<int> divisions = {24*4, 24*2, 24, 24/2, 24/4, 24/8, 2, 1}; |
|
|
|
|
|
std::vector<std::string> divisionNames = {"Whole", "Half", "Quarter", "8th", "16th", "32nd", "48th", "96th"}; |
|
|
|
|
|
for (size_t i = 0; i < divisions.size(); i++) { |
|
|
|
|
|
ClockDivisionItem *item = MenuItem::create<ClockDivisionItem>(divisionNames[i], CHECKMARK(module->divisions[index] == divisions[i])); |
|
|
|
|
|
item->module = module; |
|
|
|
|
|
item->index = index; |
|
|
|
|
|
item->division = divisions[i]; |
|
|
|
|
|
menu->addChild(item); |
|
|
|
|
|
} |
|
|
|
|
|
return menu; |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
menu->addChild(construct<MenuLabel>()); |
|
|
|
|
|
for (int i = 0; i < 2; i++) { |
|
|
|
|
|
ClockItem *item = MenuItem::create<ClockItem>(stringf("CLK %d rate", i + 1)); |
|
|
|
|
|
item->module = module; |
|
|
|
|
|
item->index = i; |
|
|
|
|
|
menu->addChild(item); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|