Browse Source

Add "Pitch bend range" setting to MIDI to CV module.

tags/v2.1.0
Andrew Belt 2 years ago
parent
commit
bdee8330c7
1 changed files with 43 additions and 16 deletions
  1. +43
    -16
      src/core/MIDI_CV.cpp

+ 43
- 16
src/core/MIDI_CV.cpp View File

@@ -35,7 +35,10 @@ struct MIDI_CV : Module {

midi::InputQueue midiInput;

/** Number of semitones to bend up/down by pitch wheel */
float pwRange;
bool smooth;
int clockDivision;
int channels;
enum PolyMode {
ROTATE_MODE,
@@ -47,7 +50,6 @@ struct MIDI_CV : Module {
PolyMode polyMode;

uint32_t clock = 0;
int clockDivision;

bool pedal;
// Indexed by channel
@@ -102,6 +104,7 @@ struct MIDI_CV : Module {
smooth = true;
channels = 1;
polyMode = ROTATE_MODE;
pwRange = 2;
clockDivision = 24;
panic();
midiInput.reset();
@@ -130,30 +133,19 @@ struct MIDI_CV : Module {
processMessage(msg);
}

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[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);
outputs[RETRIGGER_OUTPUT].setVoltage(retriggerPulses[c].process(args.sampleTime) ? 10.f : 0.f, c);
}

// Set pitch and mod wheel
// Set pitch wheel and mod wheel
int wheelChannels = (polyMode == MPE_MODE) ? 16 : 1;
float pwValues[16] = {};
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;
float pw = (int16_t(pws[c]) - 8192) / 8191.f;
pw = clamp(pw, -1.f, 1.f);
if (smooth)
pw = pwFilters[c].process(args.sampleTime, pw);
else
pwFilters[c].out = pw;
pwValues[c] = pw;
outputs[PW_OUTPUT].setVoltage(pw * 5.f);

float mod = mods[c] / 127.f;
@@ -165,6 +157,23 @@ struct MIDI_CV : Module {
outputs[MOD_OUTPUT].setVoltage(mod * 10.f);
}

// Set note outputs
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++) {
float pw = pwValues[(polyMode == MPE_MODE) ? c : 0];
float pitch = (notes[c] - 60.f + pw * pwRange) / 12.f;
outputs[PITCH_OUTPUT].setVoltage(pitch, 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);
outputs[RETRIGGER_OUTPUT].setVoltage(retriggerPulses[c].process(args.sampleTime) ? 10.f : 0.f, c);
}

// Set clock and transport outputs
outputs[CLOCK_OUTPUT].setVoltage(clockPulse.process(args.sampleTime) ? 10.f : 0.f);
outputs[CLOCK_DIV_OUTPUT].setVoltage(clockDividerPulse.process(args.sampleTime) ? 10.f : 0.f);
outputs[START_OUTPUT].setVoltage(startPulse.process(args.sampleTime) ? 10.f : 0.f);
@@ -426,6 +435,7 @@ struct MIDI_CV : Module {

json_t* dataToJson() override {
json_t* rootJ = json_object();
json_object_set_new(rootJ, "pwRange", json_real(pwRange));
json_object_set_new(rootJ, "smooth", json_boolean(smooth));
json_object_set_new(rootJ, "channels", json_integer(channels));
json_object_set_new(rootJ, "polyMode", json_integer(polyMode));
@@ -440,6 +450,13 @@ struct MIDI_CV : Module {
}

void dataFromJson(json_t* rootJ) override {
json_t* pwRangeJ = json_object_get(rootJ, "pwRange");
if (pwRangeJ)
pwRange = json_number_value(pwRangeJ);
// For backwards compatibility, set to 0 if undefined in JSON.
else
pwRange = 0;

json_t* smoothJ = json_object_get(rootJ, "smooth");
if (smoothJ)
smooth = json_boolean_value(smoothJ);
@@ -510,6 +527,16 @@ struct MIDI_CVWidget : ModuleWidget {

menu->addChild(new MenuSeparator);

static const std::vector<float> pwRanges = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 24, 36, 48};
menu->addChild(createSubmenuItem("Pitch bend range", string::f("%g", module->pwRange), [=](Menu* menu) {
for (size_t i = 0; i < pwRanges.size(); i++) {
menu->addChild(createCheckMenuItem(string::f("%g", pwRanges[i]), "",
[=]() {return module->pwRange == pwRanges[i];},
[=]() {module->pwRange = pwRanges[i];}
));
}
}));

menu->addChild(createBoolPtrMenuItem("Smooth pitch/mod wheel", "", &module->smooth));

static const std::vector<int> clockDivisions = {24 * 4, 24 * 2, 24, 24 / 2, 24 / 4, 24 / 8, 2, 1};


Loading…
Cancel
Save