summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2014-06-08 14:48:10 +0200
committerRobin Gareus <robin@gareus.org>2014-06-08 14:48:10 +0200
commiteb289a76afc8c59c52ba4fe874cc9ba6a47d57b4 (patch)
treefc73705c0a6d11766f128da7424111af12111f1c /gtk2_ardour
parent81182b5bf69e06f67b3ccbca46860ac8e6387d2f (diff)
basic Midi latency measurement GUI (re-use Audio latency notebook)
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/engine_dialog.cc202
-rw-r--r--gtk2_ardour/engine_dialog.h10
2 files changed, 149 insertions, 63 deletions
diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc
index af6ebc28c1..9429fe5bcc 100644
--- a/gtk2_ardour/engine_dialog.cc
+++ b/gtk2_ardour/engine_dialog.cc
@@ -40,6 +40,7 @@
#include "ardour/audio_backend.h"
#include "ardour/audioengine.h"
#include "ardour/mtdm.h"
+#include "ardour/mididm.h"
#include "ardour/rc_configuration.h"
#include "ardour/types.h"
@@ -80,7 +81,8 @@ EngineControl::EngineControl ()
, lm_measure_label (_("Measure"))
, lm_use_button (_("Use results"))
, lm_back_button (_("Back to settings ... (ignore results)"))
- , lm_button (_("Calibrate..."))
+ , lm_button_audio (_("Calibrate Audio"))
+ , lm_button_midi (_("Calibrate Midi"))
, lm_table (12, 3)
, have_lm_results (false)
, lm_running (false)
@@ -88,6 +90,7 @@ EngineControl::EngineControl ()
, ignore_changes (0)
, _desired_sample_rate (0)
, started_at_least_once (false)
+ , _measure_midi(false)
{
using namespace Notebook_Helpers;
vector<string> strings;
@@ -335,8 +338,12 @@ EngineControl::EngineControl ()
basic_packer.attach (*label, 0, 1, 0, 1, xopt, (AttachOptions) 0);
basic_packer.attach (backend_combo, 1, 2, 0, 1, xopt, (AttachOptions) 0);
- lm_button.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_latency));
- lm_button.set_name ("generic button");
+ lm_button_audio.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_audio_latency));
+ lm_button_audio.set_name ("generic button");
+
+ lm_button_midi.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_midi_latency));
+ lm_button_midi.set_name ("generic button");
+
if (_have_control) {
build_full_control_notebook ();
} else {
@@ -445,12 +452,13 @@ EngineControl::EngineControl ()
/* button spans 2 rows */
- basic_packer.attach (lm_button, 3, 4, row-1, row+1, xopt, xopt);
+ basic_packer.attach (lm_button_audio, 3, 4, row-1, row+1, xopt, xopt);
++row;
label = manage (left_aligned_label (_("MIDI System")));
basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
basic_packer.attach (midi_option_combo, 1, 2, row, row + 1, SHRINK, (AttachOptions) 0);
+ basic_packer.attach (lm_button_midi, 3, 4, row, row+1, xopt, xopt);
row++;
}
@@ -515,8 +523,9 @@ EngineControl::EngineControl ()
vector<string> outputs;
vector<string> inputs;
- ARDOUR::AudioEngine::instance()->get_physical_outputs (ARDOUR::DataType::AUDIO, outputs);
- ARDOUR::AudioEngine::instance()->get_physical_inputs (ARDOUR::DataType::AUDIO, inputs);
+ ARDOUR::DataType const type = _measure_midi ? ARDOUR::DataType::MIDI : ARDOUR::DataType::AUDIO;
+ ARDOUR::AudioEngine::instance()->get_physical_outputs (type, outputs);
+ ARDOUR::AudioEngine::instance()->get_physical_inputs (type, inputs);
if (inputs.empty() || outputs.empty()) {
MessageDialog msg (_("Your selected audio configuration is playback- or capture-only.\n\nLatency calibration requires playback and capture"));
@@ -1639,58 +1648,117 @@ EngineControl::EngineControl ()
/* latency measurement */
- bool
- EngineControl::check_latency_measurement ()
- {
- MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
+bool
+EngineControl::check_audio_latency_measurement ()
+{
+ MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
- if (mtdm->resolve () < 0) {
- lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
- return true;
- }
+ if (mtdm->resolve () < 0) {
+ lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
+ return true;
+ }
- if (mtdm->err () > 0.3) {
- mtdm->invert ();
- mtdm->resolve ();
- }
+ if (mtdm->err () > 0.3) {
+ mtdm->invert ();
+ mtdm->resolve ();
+ }
- char buf[128];
- ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
+ char buf[256];
+ ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
- if (sample_rate == 0) {
- lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
- ARDOUR::AudioEngine::instance()->stop_latency_detection ();
- return false;
- }
+ if (sample_rate == 0) {
+ lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
+ ARDOUR::AudioEngine::instance()->stop_latency_detection ();
+ return false;
+ }
- uint32_t frames_total = mtdm->del();
- uint32_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
+ int frames_total = mtdm->del();
+ int extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
- snprintf (buf, sizeof (buf), "%u samples / %.3lf ms", extra, extra * 1000.0f/sample_rate);
+ snprintf (buf, sizeof (buf), "%s%d samples (%.3lf ms)\n%s%d samples (%.3lf ms)",
+ _("Detected roundtrip latency: "),
+ frames_total, frames_total * 1000.0f/sample_rate,
+ _("Systemic latency: "),
+ extra, extra * 1000.0f/sample_rate);
- bool solid = true;
+ bool solid = true;
- if (mtdm->err () > 0.2) {
- strcat (buf, " ");
- strcat (buf, _("(signal detection error)"));
- solid = false;
- }
+ if (mtdm->err () > 0.2) {
+ strcat (buf, " ");
+ strcat (buf, _("(signal detection error)"));
+ solid = false;
+ }
- if (mtdm->inv ()) {
- strcat (buf, " ");
- strcat (buf, _("(inverted - bad wiring)"));
- solid = false;
- }
+ if (mtdm->inv ()) {
+ strcat (buf, " ");
+ strcat (buf, _("(inverted - bad wiring)"));
+ solid = false;
+ }
- if (solid) {
- end_latency_detection ();
- lm_use_button.set_sensitive (true);
- have_lm_results = true;
- }
-
- lm_results.set_markup (string_compose (results_markup, string_compose (_("Detected roundtrip latency: %1"), buf)));
+ if (solid) {
+ end_latency_detection ();
+ lm_use_button.set_sensitive (true);
+ have_lm_results = true;
+ }
+
+ lm_results.set_markup (string_compose (results_markup, buf));
+
+ return true;
+}
+
+bool
+EngineControl::check_midi_latency_measurement ()
+{
+ ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
+
+ if (!mididm->have_signal () || mididm->latency () == 0) {
+ lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
+ return true;
+ }
+
+ char buf[256];
+ ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
+
+ if (sample_rate == 0) {
+ lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
+ ARDOUR::AudioEngine::instance()->stop_latency_detection ();
+ return false;
+ }
+
+ ARDOUR::framecnt_t frames_total = mididm->latency();
+ ARDOUR::framecnt_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
+ snprintf (buf, sizeof (buf), "%s%" PRId64" samples (%.1lf ms) dev: %.2f[spl]\n%s%" PRId64" samples (%.1lf ms)",
+ _("Detected roundtrip latency: "),
+ frames_total, frames_total * 1000.0f / sample_rate, mididm->deviation (),
+ _("Systemic latency: "),
+ extra, extra * 1000.0f / sample_rate);
+
+ bool solid = true;
+
+ if (!mididm->ok ()) {
+ strcat (buf, " ");
+ strcat (buf, _("(averaging)"));
+ solid = false;
+ }
+
+ if (mididm->deviation () > 50.0) {
+ strcat (buf, " ");
+ strcat (buf, _("(too large jitter)"));
+ solid = false;
+ } else if (mididm->deviation () > 10.0) {
+ strcat (buf, " ");
+ strcat (buf, _("(large jitter)"));
+ }
- return true;
+ if (solid) {
+ end_latency_detection ();
+ lm_use_button.set_sensitive (false); // XXX TODO
+ have_lm_results = true;
+ }
+
+ lm_results.set_markup (string_compose (results_markup, buf));
+
+ return true;
}
void
@@ -1699,9 +1767,13 @@ EngineControl::start_latency_detection ()
ARDOUR::AudioEngine::instance()->set_latency_input_port (lm_input_channel_combo.get_active_text());
ARDOUR::AudioEngine::instance()->set_latency_output_port (lm_output_channel_combo.get_active_text());
- if (ARDOUR::AudioEngine::instance()->start_latency_detection (false) == 0) {
+ if (ARDOUR::AudioEngine::instance()->start_latency_detection (_measure_midi) == 0) {
lm_results.set_markup (string_compose (results_markup, _("Detecting ...")));
- latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_latency_measurement), 100);
+ if (_measure_midi) {
+ latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_midi_latency_measurement), 100);
+ } else {
+ latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_audio_latency_measurement), 100);
+ }
lm_measure_label.set_text (_("Cancel"));
have_lm_results = false;
lm_use_button.set_sensitive (false);
@@ -1734,24 +1806,26 @@ EngineControl::latency_button_clicked ()
start_latency_detection ();
} else {
end_latency_detection ();
- }
+ }
}
void
EngineControl::use_latency_button_clicked ()
{
- MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
+ if (_measure_midi) {
+ MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
- if (!mtdm) {
- return;
- }
+ if (!mtdm) {
+ return;
+ }
- uint32_t frames_total = mtdm->del();
- uint32_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
- uint32_t one_way = extra/2;
+ uint32_t frames_total = mtdm->del();
+ uint32_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
+ uint32_t one_way = extra/2;
- input_latency_adjustment.set_value (one_way);
- output_latency_adjustment.set_value (one_way);
+ input_latency_adjustment.set_value (one_way);
+ output_latency_adjustment.set_value (one_way);
+ }
/* back to settings page */
@@ -1809,8 +1883,16 @@ EngineControl::connect_disconnect_click()
}
void
-EngineControl::calibrate_latency ()
+EngineControl::calibrate_audio_latency ()
+{
+ _measure_midi = false;
+ notebook.set_current_page (latency_tab);
+}
+
+void
+EngineControl::calibrate_midi_latency ()
{
+ _measure_midi = true;
notebook.set_current_page (latency_tab);
}
diff --git a/gtk2_ardour/engine_dialog.h b/gtk2_ardour/engine_dialog.h
index 6d10eb76ac..bb077d0705 100644
--- a/gtk2_ardour/engine_dialog.h
+++ b/gtk2_ardour/engine_dialog.h
@@ -90,7 +90,8 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
Gtk::Button lm_measure_button;
Gtk::Button lm_use_button;
Gtk::Button lm_back_button;
- ArdourButton lm_button;
+ ArdourButton lm_button_audio;
+ ArdourButton lm_button_midi;
Gtk::Label lm_title;
Gtk::Label lm_results;
Gtk::Table lm_table;
@@ -196,7 +197,8 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
/* latency measurement */
void latency_button_clicked ();
- bool check_latency_measurement ();
+ bool check_audio_latency_measurement ();
+ bool check_midi_latency_measurement ();
sigc::connection latency_timeout;
void enable_latency_tab ();
void disable_latency_tab ();
@@ -212,7 +214,9 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
PBD::ScopedConnection stopped_connection;
void connect_disconnect_click ();
- void calibrate_latency ();
+ void calibrate_audio_latency ();
+ void calibrate_midi_latency ();
+ bool _measure_midi;
};
#endif /* __gtk2_ardour_engine_dialog_h__ */