From 898f13cd911e687b399de2dbdc2be8b0854848f0 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 7 Aug 2019 12:16:44 -0400 Subject: [PATCH] MIDI-Map: re-enable filtering. MIDI-Map: fix param/filter value initialization. MIDI-CV: refactor. --- include/dsp/filter.hpp | 8 +++++ src/core/MIDI_CC.cpp | 11 +++---- src/core/MIDI_CV.cpp | 4 +-- src/core/MIDI_Map.cpp | 68 +++++++++++++++++++++++++----------------- 4 files changed, 55 insertions(+), 36 deletions(-) diff --git a/include/dsp/filter.hpp b/include/dsp/filter.hpp index b1360652..3a6314ec 100644 --- a/include/dsp/filter.hpp +++ b/include/dsp/filter.hpp @@ -68,6 +68,10 @@ struct TExponentialFilter { this->lambda = lambda; } + void setTau(T tau) { + this->lambda = 1 / tau; + } + T process(T deltaTime, T in) { T y = out + (in - out) * lambda * deltaTime; // If no change was made between the old and new output, assume T granularity is too small and snap output to input @@ -98,6 +102,10 @@ struct TPeakFilter { this->lambda = lambda; } + void setTau(T tau) { + this->lambda = 1 / tau; + } + T process(T deltaTime, T in) { T y = out + (in - out) * lambda * deltaTime; out = simd::fmax(y, in); diff --git a/src/core/MIDI_CC.cpp b/src/core/MIDI_CC.cpp index 1eb3566d..c06f0388 100644 --- a/src/core/MIDI_CC.cpp +++ b/src/core/MIDI_CC.cpp @@ -25,12 +25,11 @@ struct MIDI_CC : Module { int learningId; int learnedCcs[16]; dsp::ExponentialFilter valueFilters[16]; - int8_t lastValues[16] = {}; MIDI_CC() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); for (int i = 0; i < 16; i++) { - valueFilters[i].lambda = 1 / 0.01f; + valueFilters[i].setTau(1 / 30.f); } onReset(); } @@ -57,11 +56,10 @@ struct MIDI_CC : Module { continue; int cc = learnedCcs[i]; - - float value = rescale(values[cc], 0, 127, 0.f, 10.f); + float value = values[cc] / 127.f; // Detect behavior from MIDI buttons. - if ((lastValues[i] == 0 && values[cc] == 127) || (lastValues[i] == 127 && values[cc] == 0)) { + if (std::fabs(valueFilters[i].out - value) >= 1.f) { // Jump value valueFilters[i].out = value; } @@ -69,8 +67,7 @@ struct MIDI_CC : Module { // Smooth value with filter valueFilters[i].process(args.sampleTime, value); } - lastValues[i] = values[cc]; - outputs[CC_OUTPUT + i].setVoltage(valueFilters[i].out); + outputs[CC_OUTPUT + i].setVoltage(valueFilters[i].out * 10.f); } } diff --git a/src/core/MIDI_CV.cpp b/src/core/MIDI_CV.cpp index 23c9846e..270829f9 100644 --- a/src/core/MIDI_CV.cpp +++ b/src/core/MIDI_CV.cpp @@ -74,8 +74,8 @@ struct MIDI_CV : Module { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); heldNotes.reserve(128); for (int c = 0; c < 16; c++) { - pitchFilters[c].lambda = 1 / 0.01f; - modFilters[c].lambda = 1 / 0.01f; + pitchFilters[c].setTau(1 / 30.f); + modFilters[c].setTau(1 / 30.f); } onReset(); } diff --git a/src/core/MIDI_Map.cpp b/src/core/MIDI_Map.cpp index 38e44d1e..7435bf8d 100644 --- a/src/core/MIDI_Map.cpp +++ b/src/core/MIDI_Map.cpp @@ -42,6 +42,8 @@ struct MIDI_Map : Module { int8_t values[128]; /** The smoothing processor (normalized between 0 and 1) of each channel */ dsp::ExponentialFilter valueFilters[MAX_CHANNELS]; + bool filterInitialized[MAX_CHANNELS] = {}; + dsp::ClockDivider divider; MIDI_Map() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); @@ -49,6 +51,10 @@ struct MIDI_Map : Module { paramHandles[id].color = nvgRGB(0xff, 0xff, 0x40); APP->engine->addParamHandle(¶mHandles[id]); } + for (int i = 0; i < MAX_CHANNELS; i++) { + valueFilters[i].setTau(1 / 30.f); + } + divider.setDivision(32); onReset(); } @@ -71,38 +77,46 @@ struct MIDI_Map : Module { } void process(const ProcessArgs& args) override { - midi::Message msg; - while (midiInput.shift(&msg)) { - processMessage(msg); - } + if (divider.process()) { + midi::Message msg; + while (midiInput.shift(&msg)) { + processMessage(msg); + } - // Step channels - for (int id = 0; id < mapLen; id++) { - int cc = ccs[id]; - if (cc < 0) - continue; - // Check if CC value has been set - if (values[cc] < 0) - continue; - // Get Module - Module* module = paramHandles[id].module; - if (!module) - continue; - // Get ParamQuantity - int paramId = paramHandles[id].paramId; - ParamQuantity* paramQuantity = module->paramQuantities[paramId]; - if (!paramQuantity) - continue; - if (!paramQuantity->isBounded()) - continue; - // Set ParamQuantity - float v = rescale(values[cc], 0, 127, 0.f, 1.f); - v = valueFilters[id].process(args.sampleTime, v); - paramQuantity->setScaledValue(v); + // Step channels + for (int id = 0; id < mapLen; id++) { + int cc = ccs[id]; + if (cc < 0) + continue; + // Get Module + Module* module = paramHandles[id].module; + if (!module) + continue; + // Get ParamQuantity + int paramId = paramHandles[id].paramId; + ParamQuantity* paramQuantity = module->paramQuantities[paramId]; + if (!paramQuantity) + continue; + if (!paramQuantity->isBounded()) + continue; + // Set filter from param value if filter is uninitialized + if (!filterInitialized[id]) { + valueFilters[id].out = paramQuantity->getScaledValue(); + filterInitialized[id] = true; + } + // Set param if value has been initialized + if (values[cc] >= 0) { + float v = values[cc] / 127.f; + v = valueFilters[id].process(args.sampleTime * divider.getDivision(), v); + paramQuantity->setScaledValue(v); + } + } } } void processMessage(midi::Message msg) { + // DEBUG("MIDI: %01x %01x %02x %02x", msg.getStatus(), msg.getChannel(), msg.getNote(), msg.getValue()); + switch (msg.getStatus()) { // cc case 0xb: {