]> git.sesse.net Git - nageru/blobdiff - nageru/delay_analyzer.cpp
Make an automated delay estimate, by way of cross-correlation.
[nageru] / nageru / delay_analyzer.cpp
index 9e8206015de30a80ce74455a0efdd9d12ff6f19f..b3127c4630567db073871b7f1505218a1028999b 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "audio_mixer.h"
 #include "ui_delay_analyzer.h"
+#include "shared/post_to_main_thread.h"
 
 #include <bmusb/bmusb.h>
 
@@ -53,6 +54,7 @@ void DelayAnalyzer::grab_clicked()
        grab_timeout->start(milliseconds(2000));
        clip1.clear();
        clip2.clear();
+       ui->delay_estimate_label->clear();
        ui->peak_display_1->reset_base();
        ui->peak_display_2->reset_base();
        ui->peak_display_1->audio_clip_updated();
@@ -90,6 +92,7 @@ void DelayAnalyzer::card_selected(QComboBox *card_combo, int selected_index)
                clip2.clear();
                ui->peak_display_2->audio_clip_updated();
        }
+       ui->delay_estimate_label->clear();
 }
 
 void DelayAnalyzer::channel_selected(QComboBox *channel_combo)
@@ -101,6 +104,7 @@ void DelayAnalyzer::channel_selected(QComboBox *channel_combo)
                clip2.clear();
                ui->peak_display_2->audio_clip_updated();
        }
+       ui->delay_estimate_label->clear();
 }
 
 DeviceSpec DelayAnalyzer::get_selected_device(QComboBox *card_combo)
@@ -152,7 +156,29 @@ void DelayAnalyzer::add_audio(DeviceSpec device_spec, const uint8_t *data, unsig
                        grab_timeout->stop();
                });
                grabbing = false;
+
+               // The delay estimation is cheap, but it's not free, and we're on the main mixer thread,
+               // so fire it off onto a background thread.
+               std::thread(&DelayAnalyzer::estimate_delay, this).detach();
+       }
+}
+
+void DelayAnalyzer::estimate_delay()
+{
+       AudioClip::BestCorrelation corr = clip1.find_best_correlation(&clip2);
+       char buf[256];
+       if (isnan(corr.correlation) || fabs(corr.correlation) < 0.1) {  // Very loose bound, basically to guard against digital silence.
+               snprintf(buf, sizeof(buf), "Could not estimate delay.\n");
+       } else if (corr.correlation < 0.0) {
+               snprintf(buf, sizeof(buf), "Best estimate: Channel is %.1f ms delayed compared to reference <em>and inverted</em> (correlation = %.3f)\n",
+                       corr.delay_ms, corr.correlation);
+       } else {
+               snprintf(buf, sizeof(buf), "Best estimate: Channel is %.1f ms delayed compared to reference (correlation = %.3f)\n",
+                       corr.delay_ms, corr.correlation);
        }
+       post_to_main_thread([this, buf] {
+               ui->delay_estimate_label->setText(buf);
+       });
 }
 
 void DelayAnalyzer::grab_timed_out()