|
@@ -19,11 +19,10 @@ struct MIDICCToCVInterface : Module { |
|
|
|
|
|
|
|
|
midi::InputQueue midiInput; |
|
|
midi::InputQueue midiInput; |
|
|
int8_t values[128]; |
|
|
int8_t values[128]; |
|
|
dsp::ExponentialFilter valueFilters[16]; |
|
|
|
|
|
|
|
|
|
|
|
int learningId = -1; |
|
|
int learningId = -1; |
|
|
int ccs[16] = {}; |
|
|
int ccs[16] = {}; |
|
|
bool jump[16] = {}; |
|
|
|
|
|
|
|
|
dsp::ExponentialFilter valueFilters[16]; |
|
|
|
|
|
int8_t lastValues[16] = {}; |
|
|
|
|
|
|
|
|
MIDICCToCVInterface() { |
|
|
MIDICCToCVInterface() { |
|
|
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); |
|
|
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); |
|
@@ -48,17 +47,24 @@ struct MIDICCToCVInterface : Module { |
|
|
|
|
|
|
|
|
float lambda = app()->engine->getSampleTime() * 100.f; |
|
|
float lambda = app()->engine->getSampleTime() * 100.f; |
|
|
for (int i = 0; i < 16; i++) { |
|
|
for (int i = 0; i < 16; i++) { |
|
|
int learnedCc = ccs[i]; |
|
|
|
|
|
float value = rescale(values[learnedCc], 0, 127, 0.f, 10.f); |
|
|
|
|
|
|
|
|
if (!outputs[CC_OUTPUT + i].active) |
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
int cc = ccs[i]; |
|
|
|
|
|
|
|
|
|
|
|
float value = rescale(values[cc], 0, 127, 0.f, 10.f); |
|
|
valueFilters[i].lambda = lambda; |
|
|
valueFilters[i].lambda = lambda; |
|
|
// Smooth value unless we're jumping there |
|
|
|
|
|
if (jump[i]) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Detect behavior from MIDI buttons. |
|
|
|
|
|
if ((lastValues[i] == 0 && values[cc] == 127) || (lastValues[i] == 127 && values[cc] == 0)) { |
|
|
|
|
|
// Jump value |
|
|
valueFilters[i].out = value; |
|
|
valueFilters[i].out = value; |
|
|
jump[i] = false; |
|
|
|
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
|
|
|
// Smooth value with filter |
|
|
valueFilters[i].process(value); |
|
|
valueFilters[i].process(value); |
|
|
} |
|
|
} |
|
|
|
|
|
lastValues[i] = values[cc]; |
|
|
outputs[CC_OUTPUT + i].setVoltage(valueFilters[i].out); |
|
|
outputs[CC_OUTPUT + i].setVoltage(valueFilters[i].out); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@@ -73,15 +79,9 @@ struct MIDICCToCVInterface : Module { |
|
|
ccs[learningId] = cc; |
|
|
ccs[learningId] = cc; |
|
|
learningId = -1; |
|
|
learningId = -1; |
|
|
} |
|
|
} |
|
|
int8_t oldValue = values[cc]; |
|
|
|
|
|
// Allow CC to be negative if the 8th bit is set. |
|
|
// Allow CC to be negative if the 8th bit is set. |
|
|
// The gamepad driver abuses this, for example. |
|
|
// The gamepad driver abuses this, for example. |
|
|
int8_t value = msg.data2; |
|
|
|
|
|
// Detect behavior from MIDI buttons. |
|
|
|
|
|
// Don't run these through a smoothing filter. |
|
|
|
|
|
if ((oldValue == 0 && value == 127) || (oldValue == 127 && value == 0)) |
|
|
|
|
|
jump[cc] = true; |
|
|
|
|
|
values[cc] = value; |
|
|
|
|
|
|
|
|
values[cc] = msg.data2; |
|
|
} break; |
|
|
} break; |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
@@ -125,10 +125,6 @@ struct MIDICCToCVInterface : Module { |
|
|
values[i] = json_integer_value(valueJ); |
|
|
values[i] = json_integer_value(valueJ); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
// Jump all CCs |
|
|
|
|
|
for (int i = 0; i < 16; i++) { |
|
|
|
|
|
jump[i] = true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
json_t *midiJ = json_object_get(rootJ, "midi"); |
|
|
json_t *midiJ = json_object_get(rootJ, "midi"); |
|
|