Change the tap tempo estimator to least-squares regression

This commit is contained in:
Pavel Potocek 2016-01-13 15:04:29 +01:00 committed by Tim Mayberry
parent ec708926fa
commit 8d408d000d
2 changed files with 28 additions and 27 deletions

View File

@ -267,39 +267,38 @@ TempoDialog::pulse_change ()
bool bool
TempoDialog::tap_tempo_button_press (GdkEventButton *ev) TempoDialog::tap_tempo_button_press (GdkEventButton *ev)
{ {
gint64 now; double t;
now = g_get_monotonic_time (); // microseconds
// Linear least-squares regression
if (tapped) { if (tapped) {
double interval, bpm; t = 1e-6 * (g_get_monotonic_time () - first_t); // Subtract first_t to avoid precision problems
static const double decay = 0.5;
interval = (now - last_tap) * 1.0e-6; double n = tap_count;
if (interval <= 6.0) { sum_y += t;
// <= 6 seconds (say): >= 10 bpm sum_x += n;
if (average_interval > 0) { sum_xy += n * t;
if (average_interval > interval / 1.2 && average_interval < interval * 1.2) { sum_xx += n * n;
average_interval = interval * decay double T = (sum_xy/n - sum_x/n * sum_y/n) / (sum_xx/n - sum_x/n * sum_x/n);
+ average_interval * (1.0-decay);
} else {
average_interval = 0;
}
} else {
average_interval = interval;
}
if (average_interval > 0) { if (t - last_t < T / 1.2 || t - last_t > T * 1.2) {
bpm = 60.0 / average_interval; tapped = false;
bpm_spinner.set_value (bpm);
}
} else { } else {
average_interval = 0; bpm_spinner.set_value (60.0 / T);
} }
} else { }
average_interval = 0; if (!tapped) {
first_t = g_get_monotonic_time ();
t = 0.0;
sum_y = 0.0;
sum_x = 1.0;
sum_xy = 0.0;
sum_xx = 1.0;
tap_count = 1.0;
tapped = true; tapped = true;
} }
last_tap = now; tap_count++;
last_t = t;
return true; return true;
} }

View File

@ -60,8 +60,10 @@ private:
NoteTypes note_types; NoteTypes note_types;
bool tapped; // whether the tap-tempo button has been clicked bool tapped; // whether the tap-tempo button has been clicked
gint64 last_tap; double sum_x, sum_xx, sum_xy, sum_y;
double average_interval; double tap_count;
double last_t;
gint64 first_t;
Gtk::ComboBoxText pulse_selector; Gtk::ComboBoxText pulse_selector;
Gtk::Adjustment bpm_adjustment; Gtk::Adjustment bpm_adjustment;