Browse Source

Add MIDITriggerToCVInterface skeleton

pull/1639/head
Andrew Belt 7 years ago
parent
commit
b8c6c75c1b
6 changed files with 145 additions and 286 deletions
  1. +0
    -0
      src/core/MIDICCToCVInterface.cpp
  2. +143
    -0
      src/core/MIDITriggerToCVInterface.cpp
  3. +0
    -286
      src/core/MidiTriggerToCV.cpp
  4. +0
    -0
      src/core/QuadMIDIToCVInterface.cpp
  5. +1
    -0
      src/core/core.cpp
  6. +1
    -0
      src/core/core.hpp

src/core/MidiCCToCV.cpp → src/core/MIDICCToCVInterface.cpp View File


+ 143
- 0
src/core/MIDITriggerToCVInterface.cpp View File

@@ -0,0 +1,143 @@
#include "core.hpp"
#include "midi.hpp"
#include "dsp/filter.hpp"



struct CcChoice : LedDisplayChoice {
CcChoice() {
box.size.y = mm2px(6.666);
textOffset.y -= 4;
}
};


struct CcMidiWidget : MidiWidget {
LedDisplaySeparator *hSeparators[4];
LedDisplaySeparator *vSeparators[4];
LedDisplayChoice *ccChoices[4][4];

CcMidiWidget() {
Vec pos = channelChoice->box.getBottomLeft();
for (int x = 1; x < 4; x++) {
vSeparators[x] = Widget::create<LedDisplaySeparator>(pos);
addChild(vSeparators[x]);
}
for (int y = 0; y < 4; y++) {
hSeparators[y] = Widget::create<LedDisplaySeparator>(pos);
addChild(hSeparators[y]);
for (int x = 0; x < 4; x++) {
CcChoice *ccChoice = Widget::create<CcChoice>(pos);
ccChoice->text = stringf("%d", x*4+y);
ccChoices[x][y] = ccChoice;
addChild(ccChoice);
}
pos = ccChoices[0][y]->box.getBottomLeft();
}
for (int x = 1; x < 4; x++) {
vSeparators[x]->box.size.y = pos.y - vSeparators[x]->box.pos.y;
}
}
void step() override {
MidiWidget::step();
for (int x = 1; x < 4; x++) {
vSeparators[x]->box.pos.x = box.size.x / 4 * x;
}
for (int y = 0; y < 4; y++) {
hSeparators[y]->box.size.x = box.size.x;
for (int x = 0; x < 4; x++) {
ccChoices[x][y]->box.size.x = box.size.x / 4;
ccChoices[x][y]->box.pos.x = box.size.x / 4 * x;
}
}
}
};


struct MIDITriggerToCVInterface : Module {
enum ParamIds {
NUM_PARAMS
};
enum InputIds {
NUM_INPUTS
};
enum OutputIds {
ENUMS(TRIG_OUTPUT, 16),
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};

MidiInputQueue midiInput;

MIDITriggerToCVInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}

void step() override {
MidiMessage msg;
while (midiInput.shift(&msg)) {
processMessage(msg);
}

for (int i = 0; i < 16; i++) {
outputs[TRIG_OUTPUT + i].value = 0.f;
}
}

void processMessage(MidiMessage msg) {
// debug("MIDI: %01x %01x %02x %02x", msg.status(), msg.channel(), msg.data1, msg.data2);

switch (msg.status()) {
default: break;
}
}

json_t *toJson() override {
json_t *rootJ = json_object();
json_object_set_new(rootJ, "midi", midiInput.toJson());
return rootJ;
}

void fromJson(json_t *rootJ) override {
json_t *midiJ = json_object_get(rootJ, "midi");
midiInput.fromJson(midiJ);
}
};


struct MIDITriggerToCVInterfaceWidget : ModuleWidget {
MIDITriggerToCVInterfaceWidget(MIDITriggerToCVInterface *module) : ModuleWidget(module) {
setPanel(SVG::load(assetGlobal("res/Core/MIDICCToCVInterface.svg")));

addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

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

MidiWidget *midiWidget = Widget::create<CcMidiWidget>(mm2px(Vec(3.399621, 14.837339)));
midiWidget->box.size = mm2px(Vec(44, 54.667));
midiWidget->midiIO = &module->midiInput;
addChild(midiWidget);

}
};


Model *modelMIDITriggerToCVInterface = Model::create<MIDITriggerToCVInterface, MIDITriggerToCVInterfaceWidget>("Core", "MIDITriggerToCVInterface", "MIDI-TRIG", MIDI_TAG, EXTERNAL_TAG);

+ 0
- 286
src/core/MidiTriggerToCV.cpp View File

@@ -1,286 +0,0 @@
#if 0
#include <list>
#include <algorithm>
#include "core.hpp"
#include "MidiIO.hpp"
#include "dsp/digital.hpp"


using namespace rack;

struct TriggerValue {
int val = 0;
int num;
bool numInited = false;
bool onFocus = false;
};

struct MIDITriggerToCVInterface : MidiIO, Module {
enum ParamIds {
NUM_PARAMS
};
enum InputIds {
NUM_INPUTS
};
enum OutputIds {
NUM_OUTPUTS = 16
};

TriggerValue trigger[NUM_OUTPUTS];

MIDITriggerToCVInterface() : MidiIO(), Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {
for (int i = 0; i < NUM_OUTPUTS; i++) {
trigger[i].num = i;
}
}

~MIDITriggerToCVInterface() {
}

void step() override;

void processMidi(std::vector<unsigned char> msg);

void resetMidi() override;

virtual json_t *toJson() override {
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(trigger[i].num));
}
return rootJ;
}

void fromJson(json_t *rootJ) override {
baseFromJson(rootJ);
for (int i = 0; i < NUM_OUTPUTS; i++) {
json_t *ccNumJ = json_object_get(rootJ, std::to_string(i).c_str());
if (ccNumJ) {
trigger[i].num = json_integer_value(ccNumJ);
trigger[i].numInited = true;
}

}
}

void onReset() override {
resetMidi();
}
};


void MIDITriggerToCVInterface::step() {
if (isPortOpen()) {
std::vector<unsigned char> message;

// midiIn->getMessage returns empty vector if there are no messages in the queue
getMessage(&message);
if (message.size() > 0) {
processMidi(message);
}
}

for (int i = 0; i < NUM_OUTPUTS; i++) {
// 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].val > 0 ? 10.0 : 0.0;
}
}

void MIDITriggerToCVInterface::resetMidi() {
for (int i = 0; i < NUM_OUTPUTS; i++) {
trigger[i].val = 0;
}
};

void MIDITriggerToCVInterface::processMidi(std::vector<unsigned char> msg) {
int channel = msg[0] & 0xf;
int status = (msg[0] >> 4) & 0xf;
int data1 = msg[1];
int data2 = msg[2];

//fprintf(stderr, "channel %d status %d data1 %d data2 %d\n", channel, status, data1,data2);

// Filter channels
if (this->channel >= 0 && this->channel != channel)
return;

if (status == 0x8) { // note off
for (int i = 0; i < NUM_OUTPUTS; i++) {
if (data1 == trigger[i].num) {
trigger[i].val = 0;
}
}
return;
}

if (status == 0x9) { // note on
for (int i = 0; i < NUM_OUTPUTS; i++) {
if (trigger[i].onFocus && data2 > 0) {
trigger[i].num = data1;
}

if (data1 == trigger[i].num) {
trigger[i].val = data2;
}
}
}

}

struct TriggerTextField : TextField {
void onTextChange() override;

void draw(NVGcontext *vg) override;

void onMouseDown(EventMouseDown &e) override;

void onMouseUp(EventMouseUp &e) override;

void onMouseLeave(EventMouseLeave &e) override;

int outNum;
MIDITriggerToCVInterface *module;
};

void TriggerTextField::draw(NVGcontext *vg) {
/* This is necessary, since the save
* file is loaded after constructing the widget*/
if (module->trigger[outNum].numInited) {
module->trigger[outNum].numInited = false;
text = std::to_string(module->trigger[outNum].num);
}

if (module->trigger[outNum].onFocus) {
text = std::to_string(module->trigger[outNum].num);
}

TextField::draw(vg);
}

void TriggerTextField::onTextChange() {
if (text.size() > 0) {
try {
int num = std::stoi(text);
// Only allow valid cc numbers
if (num < 0 || num > 127 || text.size() > 3) {
text = "";
begin = end = 0;
module->trigger[outNum].num = -1;
}
else {
module->trigger[outNum].num = num;
}
}
catch (...) {
text = "";
begin = end = 0;
module->trigger[outNum].num = -1;
}
};
}

void TriggerTextField::onMouseUp(EventMouseUp &e) {
if (e.button == 1) {
module->trigger[outNum].onFocus = false;
e.consumed = true;
}
TextField::onMouseUp(e);
}

void TriggerTextField::onMouseDown(EventMouseDown &e) {
if (e.button == 1) {
module->trigger[outNum].onFocus = true;
e.consumed = true;
}
TextField::onMouseDown(e);
}

void TriggerTextField::onMouseLeave(EventMouseLeave &e) {
module->trigger[outNum].onFocus = false;
e.consumed = true;
}

MIDITriggerToCVWidget::MIDITriggerToCVWidget() {
MIDITriggerToCVInterface *module = new MIDITriggerToCVInterface();
setModule(module);
box.size = Vec(16 * 15, 380);

{
Panel *panel = new LightPanel();
panel->box.size = box.size;
addChild(panel);
}

float margin = 5;
float labelHeight = 15;
float yPos = margin;

addChild(createScrew<ScrewSilver>(Vec(15, 0)));
addChild(createScrew<ScrewSilver>(Vec(box.size.x - 30, 0)));
addChild(createScrew<ScrewSilver>(Vec(15, 365)));
addChild(createScrew<ScrewSilver>(Vec(box.size.x - 30, 365)));
{
Label *label = new Label();
label->box.pos = Vec(box.size.x - margin - 11 * 15, margin);
label->text = "MIDI Trigger to CV";
addChild(label);
yPos = labelHeight * 2;
}

{
Label *label = new Label();
label->box.pos = Vec(margin, yPos);
label->text = "MIDI Interface";
addChild(label);

MidiChoice *midiChoice = new MidiChoice();
midiChoice->midiModule = dynamic_cast<MidiIO *>(module);
midiChoice->box.pos = Vec((box.size.x - 10) / 2 + margin, yPos);
midiChoice->box.size.x = (box.size.x / 2.0) - margin;
addChild(midiChoice);
yPos += midiChoice->box.size.y + margin;
}

{
Label *label = new Label();
label->box.pos = Vec(margin, yPos);
label->text = "Channel";
addChild(label);

ChannelChoice *channelChoice = new ChannelChoice();
channelChoice->midiModule = dynamic_cast<MidiIO *>(module);
channelChoice->box.pos = Vec((box.size.x - 10) / 2 + margin, yPos);
channelChoice->box.size.x = (box.size.x / 2.0) - margin;
addChild(channelChoice);
yPos += channelChoice->box.size.y + margin * 3;
}

for (int i = 0; i < MIDITriggerToCVInterface::NUM_OUTPUTS; i++) {
TriggerTextField *triggerNumChoice = new TriggerTextField();
triggerNumChoice->module = module;
triggerNumChoice->outNum = i;
triggerNumChoice->text = std::to_string(module->trigger[i].num);
triggerNumChoice->box.pos = Vec(11 + (i % 4) * (63), yPos);
triggerNumChoice->box.size.x = 29;

addChild(triggerNumChoice);

yPos += labelHeight + margin;
addOutput(createOutput<PJ3410Port>(Vec((i % 4) * (63) + 10, yPos + 5), module, i));

if ((i + 1) % 4 == 0) {
yPos += 47 + margin;
}
else {
yPos -= labelHeight + margin;
}
}
}

void MIDITriggerToCVWidget::step() {
ModuleWidget::step();
}
#endif

src/core/QuadMidiToCV.cpp → src/core/QuadMIDIToCVInterface.cpp View File


+ 1
- 0
src/core/core.cpp View File

@@ -9,6 +9,7 @@ void init(rack::Plugin *p) {
p->addModel(modelMIDIToCVInterface);
p->addModel(modelQuadMIDIToCVInterface);
p->addModel(modelMIDICCToCVInterface);
p->addModel(modelMIDITriggerToCVInterface);
p->addModel(modelBlank);
p->addModel(modelNotes);
}

+ 1
- 0
src/core/core.hpp View File

@@ -8,5 +8,6 @@ extern Model *modelAudioInterface;
extern Model *modelMIDIToCVInterface;
extern Model *modelQuadMIDIToCVInterface;
extern Model *modelMIDICCToCVInterface;
extern Model *modelMIDITriggerToCVInterface;
extern Model *modelBlank;
extern Model *modelNotes;

Loading…
Cancel
Save