Skip to content

Commit 898f13c

Browse files
committed
MIDI-Map: re-enable filtering.
MIDI-Map: fix param/filter value initialization. MIDI-CV: refactor.
1 parent dca30e2 commit 898f13c

File tree

4 files changed

+55
-36
lines changed

4 files changed

+55
-36
lines changed

include/dsp/filter.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ struct TExponentialFilter {
6868
this->lambda = lambda;
6969
}
7070

71+
void setTau(T tau) {
72+
this->lambda = 1 / tau;
73+
}
74+
7175
T process(T deltaTime, T in) {
7276
T y = out + (in - out) * lambda * deltaTime;
7377
// 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 {
98102
this->lambda = lambda;
99103
}
100104

105+
void setTau(T tau) {
106+
this->lambda = 1 / tau;
107+
}
108+
101109
T process(T deltaTime, T in) {
102110
T y = out + (in - out) * lambda * deltaTime;
103111
out = simd::fmax(y, in);

src/core/MIDI_CC.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,11 @@ struct MIDI_CC : Module {
2525
int learningId;
2626
int learnedCcs[16];
2727
dsp::ExponentialFilter valueFilters[16];
28-
int8_t lastValues[16] = {};
2928

3029
MIDI_CC() {
3130
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
3231
for (int i = 0; i < 16; i++) {
33-
valueFilters[i].lambda = 1 / 0.01f;
32+
valueFilters[i].setTau(1 / 30.f);
3433
}
3534
onReset();
3635
}
@@ -57,20 +56,18 @@ struct MIDI_CC : Module {
5756
continue;
5857

5958
int cc = learnedCcs[i];
60-
61-
float value = rescale(values[cc], 0, 127, 0.f, 10.f);
59+
float value = values[cc] / 127.f;
6260

6361
// Detect behavior from MIDI buttons.
64-
if ((lastValues[i] == 0 && values[cc] == 127) || (lastValues[i] == 127 && values[cc] == 0)) {
62+
if (std::fabs(valueFilters[i].out - value) >= 1.f) {
6563
// Jump value
6664
valueFilters[i].out = value;
6765
}
6866
else {
6967
// Smooth value with filter
7068
valueFilters[i].process(args.sampleTime, value);
7169
}
72-
lastValues[i] = values[cc];
73-
outputs[CC_OUTPUT + i].setVoltage(valueFilters[i].out);
70+
outputs[CC_OUTPUT + i].setVoltage(valueFilters[i].out * 10.f);
7471
}
7572
}
7673

src/core/MIDI_CV.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ struct MIDI_CV : Module {
7474
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
7575
heldNotes.reserve(128);
7676
for (int c = 0; c < 16; c++) {
77-
pitchFilters[c].lambda = 1 / 0.01f;
78-
modFilters[c].lambda = 1 / 0.01f;
77+
pitchFilters[c].setTau(1 / 30.f);
78+
modFilters[c].setTau(1 / 30.f);
7979
}
8080
onReset();
8181
}

src/core/MIDI_Map.cpp

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,19 @@ struct MIDI_Map : Module {
4242
int8_t values[128];
4343
/** The smoothing processor (normalized between 0 and 1) of each channel */
4444
dsp::ExponentialFilter valueFilters[MAX_CHANNELS];
45+
bool filterInitialized[MAX_CHANNELS] = {};
46+
dsp::ClockDivider divider;
4547

4648
MIDI_Map() {
4749
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
4850
for (int id = 0; id < MAX_CHANNELS; id++) {
4951
paramHandles[id].color = nvgRGB(0xff, 0xff, 0x40);
5052
APP->engine->addParamHandle(&paramHandles[id]);
5153
}
54+
for (int i = 0; i < MAX_CHANNELS; i++) {
55+
valueFilters[i].setTau(1 / 30.f);
56+
}
57+
divider.setDivision(32);
5258
onReset();
5359
}
5460

@@ -71,38 +77,46 @@ struct MIDI_Map : Module {
7177
}
7278

7379
void process(const ProcessArgs& args) override {
74-
midi::Message msg;
75-
while (midiInput.shift(&msg)) {
76-
processMessage(msg);
77-
}
80+
if (divider.process()) {
81+
midi::Message msg;
82+
while (midiInput.shift(&msg)) {
83+
processMessage(msg);
84+
}
7885

79-
// Step channels
80-
for (int id = 0; id < mapLen; id++) {
81-
int cc = ccs[id];
82-
if (cc < 0)
83-
continue;
84-
// Check if CC value has been set
85-
if (values[cc] < 0)
86-
continue;
87-
// Get Module
88-
Module* module = paramHandles[id].module;
89-
if (!module)
90-
continue;
91-
// Get ParamQuantity
92-
int paramId = paramHandles[id].paramId;
93-
ParamQuantity* paramQuantity = module->paramQuantities[paramId];
94-
if (!paramQuantity)
95-
continue;
96-
if (!paramQuantity->isBounded())
97-
continue;
98-
// Set ParamQuantity
99-
float v = rescale(values[cc], 0, 127, 0.f, 1.f);
100-
v = valueFilters[id].process(args.sampleTime, v);
101-
paramQuantity->setScaledValue(v);
86+
// Step channels
87+
for (int id = 0; id < mapLen; id++) {
88+
int cc = ccs[id];
89+
if (cc < 0)
90+
continue;
91+
// Get Module
92+
Module* module = paramHandles[id].module;
93+
if (!module)
94+
continue;
95+
// Get ParamQuantity
96+
int paramId = paramHandles[id].paramId;
97+
ParamQuantity* paramQuantity = module->paramQuantities[paramId];
98+
if (!paramQuantity)
99+
continue;
100+
if (!paramQuantity->isBounded())
101+
continue;
102+
// Set filter from param value if filter is uninitialized
103+
if (!filterInitialized[id]) {
104+
valueFilters[id].out = paramQuantity->getScaledValue();
105+
filterInitialized[id] = true;
106+
}
107+
// Set param if value has been initialized
108+
if (values[cc] >= 0) {
109+
float v = values[cc] / 127.f;
110+
v = valueFilters[id].process(args.sampleTime * divider.getDivision(), v);
111+
paramQuantity->setScaledValue(v);
112+
}
113+
}
102114
}
103115
}
104116

105117
void processMessage(midi::Message msg) {
118+
// DEBUG("MIDI: %01x %01x %02x %02x", msg.getStatus(), msg.getChannel(), msg.getNote(), msg.getValue());
119+
106120
switch (msg.getStatus()) {
107121
// cc
108122
case 0xb: {

0 commit comments

Comments
 (0)