Scale thresholds for hard hits

To avoid false inputs on neighboring pads for very hard hits,
thresholds can now be scaled dynamically according to the highest
input.

This is controlled by the trigger_threshold_scale_level, ranging
from 0 for no scaling to 255 for max scaling. Mind that the scaling
is non-linear and changes in the higher end of the value range have
a much larger impact.
This commit is contained in:
Frederik Walk 2023-07-16 18:00:55 +02:00
parent 305e4b7b46
commit 01536cc45d
3 changed files with 30 additions and 35 deletions

View File

@ -43,6 +43,8 @@ const Peripherals::Drum::Config drum_config = {
80, // Don Right
50, // Ka Right
},
230, // Trigger threshold scale level
50, // ADC sample count
18, // Debounce delay in milliseconds
};

View File

@ -26,6 +26,8 @@ class Drum {
} pins;
Thresholds trigger_thresholds;
uint8_t trigger_threshold_scale_level;
uint8_t sample_count;
uint16_t debounce_delay_ms;
};

View File

@ -39,42 +39,33 @@ void Drum::updateInputState(Utils::InputState &input_state) {
// Oversample ADC inputs to get rid of ADC noise
const auto raw_values = sampleInputs();
for (const auto &val : raw_values) {
switch (val.first) {
case Id::DON_LEFT:
input_state.drum.don_left.raw = val.second;
if (val.second > m_config.trigger_thresholds.don_left) {
m_pads.at(Id::DON_LEFT).setState(true, m_config.debounce_delay_ms);
} else {
m_pads.at(Id::DON_LEFT).setState(false, m_config.debounce_delay_ms);
}
break;
case Id::KA_LEFT:
input_state.drum.ka_left.raw = val.second;
if (val.second > m_config.trigger_thresholds.ka_left) {
m_pads.at(Id::KA_LEFT).setState(true, m_config.debounce_delay_ms);
} else {
m_pads.at(Id::KA_LEFT).setState(false, m_config.debounce_delay_ms);
}
break;
case Id::DON_RIGHT:
input_state.drum.don_right.raw = val.second;
if (val.second > m_config.trigger_thresholds.don_right) {
m_pads.at(Id::DON_RIGHT).setState(true, m_config.debounce_delay_ms);
} else {
m_pads.at(Id::DON_RIGHT).setState(false, m_config.debounce_delay_ms);
}
break;
case Id::KA_RIGHT:
input_state.drum.ka_right.raw = val.second;
if (val.second > m_config.trigger_thresholds.ka_right) {
m_pads.at(Id::KA_RIGHT).setState(true, m_config.debounce_delay_ms);
} else {
m_pads.at(Id::KA_RIGHT).setState(false, m_config.debounce_delay_ms);
}
break;
const auto max_value = std::max_element(raw_values.cbegin(), raw_values.cend(),
[](const auto a, const auto b) { return a.second < b.second; });
auto do_set_state = [&](const auto &id, const auto &threshold) {
// Increase threshold for very hard hits to avoid false inputs on neighboring pads
float mult = 1.0;
if (id != max_value->first && m_config.trigger_threshold_scale_level > 0) {
mult = float(max_value->second) / (((UINT8_MAX * 16) - (m_config.trigger_threshold_scale_level * 16)) + 1);
mult = mult < 1.0 ? 1.0 : mult;
}
}
if (raw_values.at(id) > (threshold * mult)) {
m_pads.at(id).setState(true, m_config.debounce_delay_ms);
} else {
m_pads.at(id).setState(false, m_config.debounce_delay_ms);
}
};
do_set_state(Id::DON_LEFT, m_config.trigger_thresholds.don_left);
do_set_state(Id::KA_LEFT, m_config.trigger_thresholds.ka_left);
do_set_state(Id::DON_RIGHT, m_config.trigger_thresholds.don_right);
do_set_state(Id::KA_RIGHT, m_config.trigger_thresholds.ka_right);
input_state.drum.don_left.raw = raw_values.at(Id::DON_LEFT);
input_state.drum.ka_left.raw = raw_values.at(Id::KA_LEFT);
input_state.drum.don_right.raw = raw_values.at(Id::DON_RIGHT);
input_state.drum.ka_right.raw = raw_values.at(Id::KA_RIGHT);
input_state.drum.don_left.triggered = m_pads.at(Id::DON_LEFT).getState();
input_state.drum.ka_left.triggered = m_pads.at(Id::KA_LEFT).getState();