diff align/Align.cpp @ 763:da57ab54f0e8

Merge from branch pitch-align. Doesn't actually do pitch alignment here, but this is the groundwork.
author Chris Cannam
date Wed, 13 May 2020 14:10:47 +0100
parents 6429a164b7e1
children dd742e566e60
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/align/Align.cpp	Wed May 13 14:10:47 2020 +0100
@@ -0,0 +1,143 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "Align.h"
+#include "TransformAligner.h"
+#include "ExternalProgramAligner.h"
+#include "framework/Document.h"
+
+#include <QSettings>
+#include <QTimer>
+
+void
+Align::alignModel(Document *doc,
+                  ModelId reference,
+                  ModelId toAlign)
+{
+    addAligner(doc, reference, toAlign);
+    m_aligners[toAlign]->begin();
+}
+
+void
+Align::scheduleAlignment(Document *doc,
+                         ModelId reference,
+                         ModelId toAlign)
+{
+    addAligner(doc, reference, toAlign);
+    int delay = 500 + 500 * int(m_aligners.size());
+    if (delay > 3500) {
+        delay = 3500;
+    }
+    SVCERR << "Align::scheduleAlignment: delaying " << delay << "ms" << endl;
+    QTimer::singleShot(delay, m_aligners[toAlign].get(), SLOT(begin()));
+}
+
+void
+Align::addAligner(Document *doc,
+                  ModelId reference,
+                  ModelId toAlign)
+{
+    bool useProgram;
+    QString program;
+    getAlignerPreference(useProgram, program);
+    
+    std::shared_ptr<Aligner> aligner;
+
+    {
+        // Replace the aligner with a new one. This also stops any
+        // previously-running alignment, when the old entry is
+        // replaced and its aligner destroyed.
+        
+        QMutexLocker locker(&m_mutex);
+    
+        if (useProgram && (program != "")) {
+            m_aligners[toAlign] =
+                std::make_shared<ExternalProgramAligner>(doc,
+                                                         reference,
+                                                         toAlign,
+                                                         program);
+        } else {
+            m_aligners[toAlign] =
+                std::make_shared<TransformAligner>(doc,
+                                                   reference,
+                                                   toAlign);
+        }
+
+        aligner = m_aligners[toAlign];
+    }
+
+    connect(aligner.get(), SIGNAL(complete(ModelId)),
+            this, SLOT(alignerComplete(ModelId)));
+
+    connect(aligner.get(), SIGNAL(failed(ModelId, QString)),
+            this, SLOT(alignerFailed(ModelId, QString)));
+}
+
+void
+Align::getAlignerPreference(bool &useProgram, QString &program)
+{
+    QSettings settings;
+    settings.beginGroup("Preferences");
+    useProgram = settings.value("use-external-alignment", false).toBool();
+    program = settings.value("external-alignment-program", "").toString();
+    settings.endGroup();
+}
+
+bool
+Align::canAlign() 
+{
+    bool useProgram;
+    QString program;
+    getAlignerPreference(useProgram, program);
+
+    if (useProgram) {
+        return ExternalProgramAligner::isAvailable(program);
+    } else {
+        return TransformAligner::isAvailable();
+    }
+}
+
+void
+Align::alignerComplete(ModelId alignmentModel)
+{
+    removeAligner(sender());
+    emit alignmentComplete(alignmentModel);
+}
+
+void
+Align::alignerFailed(ModelId toAlign, QString error)
+{
+    removeAligner(sender());
+    emit alignmentFailed(toAlign, error);
+}
+
+void
+Align::removeAligner(QObject *obj)
+{
+    Aligner *aligner = qobject_cast<Aligner *>(obj);
+    if (!aligner) {
+        SVCERR << "ERROR: Align::removeAligner: Not an Aligner" << endl;
+        return;
+    }
+
+    QMutexLocker locker (&m_mutex);
+
+    for (auto p: m_aligners) {
+        if (aligner == p.second.get()) {
+            m_aligners.erase(p.first);
+            break;
+        }
+    }
+}
+