|
|
@@ -7,10 +7,13 @@ |
|
|
|
|
|
|
|
using namespace rack; |
|
|
|
|
|
|
|
/* |
|
|
|
* MIDIToCVInterface converts midi note on/off events, velocity , channel aftertouch, pitch wheel and mod weel to |
|
|
|
* CV |
|
|
|
*/ |
|
|
|
struct TriggerValue { |
|
|
|
int val = 0; |
|
|
|
int num; |
|
|
|
bool numInited = false; |
|
|
|
bool onFocus = false; |
|
|
|
}; |
|
|
|
|
|
|
|
struct MIDITriggerToCVInterface : MidiIO, Module { |
|
|
|
enum ParamIds { |
|
|
|
NUM_PARAMS |
|
|
@@ -22,16 +25,11 @@ struct MIDITriggerToCVInterface : MidiIO, Module { |
|
|
|
NUM_OUTPUTS = 16 |
|
|
|
}; |
|
|
|
|
|
|
|
int trigger[NUM_OUTPUTS]; |
|
|
|
int triggerNum[NUM_OUTPUTS]; |
|
|
|
bool triggerNumInited[NUM_OUTPUTS]; |
|
|
|
bool onFocus[NUM_OUTPUTS]; |
|
|
|
TriggerValue trigger[NUM_OUTPUTS]; |
|
|
|
|
|
|
|
MIDITriggerToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { |
|
|
|
for (int i = 0; i < NUM_OUTPUTS; i++) { |
|
|
|
trigger[i] = 0; |
|
|
|
triggerNum[i] = i; |
|
|
|
onFocus[i] = false; |
|
|
|
trigger[i].num = i; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -48,7 +46,7 @@ struct MIDITriggerToCVInterface : MidiIO, Module { |
|
|
|
json_t *rootJ = json_object(); |
|
|
|
addBaseJson(rootJ); |
|
|
|
for (int i = 0; i < NUM_OUTPUTS; i++) { |
|
|
|
json_object_set_new(rootJ, std::to_string(i).c_str(), json_integer(triggerNum[i])); |
|
|
|
json_object_set_new(rootJ, std::to_string(i).c_str(), json_integer(trigger[i].num)); |
|
|
|
} |
|
|
|
return rootJ; |
|
|
|
} |
|
|
@@ -58,8 +56,8 @@ struct MIDITriggerToCVInterface : MidiIO, Module { |
|
|
|
for (int i = 0; i < NUM_OUTPUTS; i++) { |
|
|
|
json_t *ccNumJ = json_object_get(rootJ, std::to_string(i).c_str()); |
|
|
|
if (ccNumJ) { |
|
|
|
triggerNum[i] = json_integer_value(ccNumJ); |
|
|
|
triggerNumInited[i] = true; |
|
|
|
trigger[i].num = json_integer_value(ccNumJ); |
|
|
|
trigger[i].numInited = true; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
@@ -68,7 +66,6 @@ struct MIDITriggerToCVInterface : MidiIO, Module { |
|
|
|
void reset() final { |
|
|
|
resetMidi(); |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@@ -88,13 +85,13 @@ void MIDITriggerToCVInterface::step() { |
|
|
|
// Note: Could have an option to select between gate and velocity |
|
|
|
// but trigger seams more useful |
|
|
|
// outputs[i].value = trigger[i] / 127.0 * 10; |
|
|
|
outputs[i].value = trigger[i] > 0 ? 10.0 : 0.0; |
|
|
|
outputs[i].value = trigger[i].val > 0 ? 10.0 : 0.0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void MIDITriggerToCVInterface::resetMidi() { |
|
|
|
for (int i = 0; i < NUM_OUTPUTS; i++) { |
|
|
|
trigger[i] = 0; |
|
|
|
trigger[i].val = 0; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
@@ -112,8 +109,8 @@ void MIDITriggerToCVInterface::processMidi(std::vector<unsigned char> msg) { |
|
|
|
|
|
|
|
if (status == 0x8) { // note off |
|
|
|
for (int i = 0; i < NUM_OUTPUTS; i++) { |
|
|
|
if (data1 == triggerNum[i]) { |
|
|
|
trigger[i] = data2; |
|
|
|
if (data1 == trigger[i].num) { |
|
|
|
trigger[i].num = data2; |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
@@ -121,14 +118,14 @@ void MIDITriggerToCVInterface::processMidi(std::vector<unsigned char> msg) { |
|
|
|
|
|
|
|
if (status == 0x9) { // note on |
|
|
|
for (int i = 0; i < NUM_OUTPUTS; i++) { |
|
|
|
if (onFocus[i]) { |
|
|
|
this->triggerNum[i] = data1; |
|
|
|
if (trigger[i].onFocus) { |
|
|
|
trigger[i].num = data1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (int i = 0; i < NUM_OUTPUTS; i++) { |
|
|
|
if (data1 == triggerNum[i]) { |
|
|
|
trigger[i] = data2; |
|
|
|
if (data1 == trigger[i].num) { |
|
|
|
trigger[i].val = data2; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@@ -146,22 +143,20 @@ struct TriggerTextField : TextField { |
|
|
|
|
|
|
|
void onMouseLeave(); |
|
|
|
|
|
|
|
|
|
|
|
int *triggerNum; |
|
|
|
bool *inited; |
|
|
|
bool *onFocus; |
|
|
|
int outNum; |
|
|
|
MIDITriggerToCVInterface *module; |
|
|
|
}; |
|
|
|
|
|
|
|
void TriggerTextField::draw(NVGcontext *vg) { |
|
|
|
/* This is necessary, since the save |
|
|
|
* file is loaded after constructing the widget*/ |
|
|
|
if (*inited) { |
|
|
|
*inited = false; |
|
|
|
text = std::to_string(*triggerNum); |
|
|
|
if (module->trigger[outNum].numInited) { |
|
|
|
module->trigger[outNum].numInited = false; |
|
|
|
text = std::to_string(module->trigger[outNum].num); |
|
|
|
} |
|
|
|
|
|
|
|
if (*onFocus) { |
|
|
|
text = std::to_string(*triggerNum); |
|
|
|
if (module->trigger[outNum].onFocus) { |
|
|
|
text = std::to_string(module->trigger[outNum].num); |
|
|
|
} |
|
|
|
|
|
|
|
TextField::draw(vg); |
|
|
@@ -170,36 +165,38 @@ void TriggerTextField::draw(NVGcontext *vg) { |
|
|
|
void TriggerTextField::onTextChange() { |
|
|
|
if (text.size() > 0) { |
|
|
|
try { |
|
|
|
*triggerNum = std::stoi(text); |
|
|
|
int num = std::stoi(text); |
|
|
|
// Only allow valid cc numbers |
|
|
|
if (*triggerNum < 0 || *triggerNum > 127 || text.size() > 3) { |
|
|
|
if (num < 0 || num > 127 || text.size() > 3) { |
|
|
|
text = ""; |
|
|
|
begin = end = 0; |
|
|
|
*triggerNum = -1; |
|
|
|
module->trigger[outNum].num = -1; |
|
|
|
}else { |
|
|
|
module->trigger[outNum].num = num; |
|
|
|
} |
|
|
|
} catch (...) { |
|
|
|
text = ""; |
|
|
|
begin = end = 0; |
|
|
|
*triggerNum = -1; |
|
|
|
module->trigger[outNum].num = -1; |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
void TriggerTextField::onMouseUpOpaque(int button) { |
|
|
|
if (button == 1) { |
|
|
|
*onFocus = false; |
|
|
|
module->trigger[outNum].onFocus = false; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void TriggerTextField::onMouseDownOpaque(int button) { |
|
|
|
if (button == 1) { |
|
|
|
*onFocus = true; |
|
|
|
module->trigger[outNum].onFocus = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void TriggerTextField::onMouseLeave() { |
|
|
|
*onFocus = false; |
|
|
|
module->trigger[outNum].onFocus = false; |
|
|
|
} |
|
|
|
|
|
|
|
MIDITriggerToCVWidget::MIDITriggerToCVWidget() { |
|
|
@@ -259,10 +256,8 @@ MIDITriggerToCVWidget::MIDITriggerToCVWidget() { |
|
|
|
|
|
|
|
for (int i = 0; i < MIDITriggerToCVInterface::NUM_OUTPUTS; i++) { |
|
|
|
TriggerTextField *triggerNumChoice = new TriggerTextField(); |
|
|
|
triggerNumChoice->triggerNum = &module->triggerNum[i]; |
|
|
|
triggerNumChoice->inited = &module->triggerNumInited[i]; |
|
|
|
triggerNumChoice->onFocus = &module->onFocus[i]; |
|
|
|
triggerNumChoice->text = std::to_string(module->triggerNum[i]); |
|
|
|
triggerNumChoice->module = module; |
|
|
|
triggerNumChoice->text = std::to_string(module->trigger[i].num); |
|
|
|
triggerNumChoice->box.pos = Vec(11 + (i % 4) * (63), yPos); |
|
|
|
triggerNumChoice->box.size.x = 29; |
|
|
|
|
|
|
|