Mercurial > hg > sonic-lineup
changeset 441:7180bdbcf7cb
Merge from branch pitch-align
| author | Chris Cannam |
|---|---|
| date | Fri, 26 Jun 2020 13:52:26 +0100 |
| parents | d975dfc25e06 (current diff) 4469d30fc1bc (diff) |
| children | 49b88195961c |
| files | repoint-lock.json repoint-project.json |
| diffstat | 7 files changed, 364 insertions(+), 218 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Thu May 14 16:59:51 2020 +0100 +++ b/.hgignore Fri Jun 26 13:52:26 2020 +0100 @@ -17,9 +17,10 @@ *.orig *.rej re:^autom4te\.cache/ -re:^qrc_vect\.cpp$ +re:^qrc_.*\.cpp$ re:^vect$ re:^sonic-lineup$ +re:^sonic-vector$ re:^aclocal\.m4$ re:^config\.log$ re:^config\.pri$ @@ -62,3 +63,6 @@ ..* deploy/linux/docker/output *.AppImage +packages/ +pitch-track-align/pitch-track-align +pitch-track-align/pitch-track-align.deps
--- a/base.pri Thu May 14 16:59:51 2020 +0100 +++ b/base.pri Fri Jun 26 13:52:26 2020 +0100 @@ -31,6 +31,8 @@ win*: DEFINES += __WINDOWS_MM__ solaris*: DEFINES += __RTMIDI_DUMMY_ONLY__ +DEFINES += QT_DEPRECATED_WARNINGS_SINCE=0x050A00 + # Defines for Dataquay DEFINES += USE_SORD
--- a/main/MainWindow.cpp Thu May 14 16:59:51 2020 +0100 +++ b/main/MainWindow.cpp Fri Jun 26 13:52:26 2020 +0100 @@ -17,6 +17,7 @@ #include "MainWindow.h" #include "framework/Document.h" #include "framework/VersionTester.h" +#include "align/Align.h" #include "PreferencesDialog.h" #include "NetworkPermissionTester.h" @@ -54,6 +55,7 @@ #include "widgets/SubdividingMenu.h" #include "widgets/NotifyingPushButton.h" #include "widgets/KeyReference.h" +#include "widgets/MenuTitle.h" #include "audio/AudioCallbackPlaySource.h" #include "audio/AudioCallbackRecordTarget.h" #include "audio/PlaySpeedRangeMapper.h" @@ -113,6 +115,7 @@ #include <QCloseEvent> #include <QDialogButtonBox> #include <QTextEdit> +#include <QFileDialog> #include <iostream> #include <cstdio> @@ -135,11 +138,12 @@ int(PaneStack::Option::ShowAlignmentViews) | int(PaneStack::Option::NoCloseOnFirstPane)), m_mainMenusCreated(false), - m_playbackMenu(nullptr), + m_playbackToolBar(nullptr), m_recentSessionsMenu(nullptr), m_deleteSelectedAction(nullptr), m_ffwdAction(nullptr), m_rwdAction(nullptr), + m_previousActiveAlignmentType(Align::NoAlignment), m_recentSessions("RecentSessions", 20), m_exiting(false), m_preferencesDialog(nullptr), @@ -380,8 +384,6 @@ mainFrame->setLayout(mainLayout); setupMenus(); - setupToolbars(); - setupHelpMenu(); statusBar()->hide(); @@ -416,11 +418,19 @@ // the system menubar integration altogether. Like this: menuBar()->setNativeMenuBar(false); #endif + + setupFileMenu(); + setupViewMenu(); + setupPlaybackMenu(); + setupAlignmentMenu(); + setupHelpMenu(); + + Pane::registerShortcuts(*m_keyReference); + + } else { + setupRecentSessionsMenu(); } - setupFileMenu(); - setupViewMenu(); - m_mainMenusCreated = true; } @@ -545,6 +555,28 @@ } void +MainWindow::setupRecentSessionsMenu() +{ + m_recentSessionsMenu->clear(); + vector<pair<QString, QString>> sessions = m_recentSessions.getRecentEntries(); + for (size_t i = 0; i < sessions.size(); ++i) { + QString path = sessions[i].first; + QString label = sessions[i].second; + if (label == "") label = path; + QAction *action = m_recentSessionsMenu->addAction(label); + action->setObjectName(path); + connect(action, SIGNAL(triggered()), this, SLOT(openRecentSession())); + if (i == 0) { + action->setShortcut(tr("Ctrl+R")); + m_keyReference->registerShortcut + (tr("Re-open"), + action->shortcut().toString(), + tr("Re-open the current or most recently opened session")); + } + } +} + +void MainWindow::setupViewMenu() { if (m_mainMenusCreated) return; @@ -716,6 +748,175 @@ } void +MainWindow::setupAlignmentMenu() +{ + m_keyReference->setCategory(tr("Alignment")); + + IconLoader il; + + QMenu *menu = menuBar()->addMenu(tr("&Alignment")); + menu->setTearOffEnabled(false); + + QActionGroup *alignmentGroup = new QActionGroup(this); + +//!!! + explanatory status bar texts + + map<Align::AlignmentType, QString> alignmentLabels { + { Align::NoAlignment, tr("No Alignment") }, + { Align::LinearAlignment, tr("Linear") }, + { Align::TrimmedLinearAlignment, tr("Linear Trimmed") }, + { Align::MATCHAlignment, tr("MATCH Aligner") }, + { Align::MATCHAlignmentWithPitchCompare, tr("MATCH with Tuning Compensation") }, + { Align::SungNoteContourAlignment, tr("Sung Note Contour") }, + }; + + QAction *action = nullptr; + Align::AlignmentType preference = Align::getAlignmentPreference(); + + for (auto al: alignmentLabels) { + action = menu->addAction(al.second); + action->setObjectName(Align::getAlignmentTypeTag(al.first)); + action->setActionGroup(alignmentGroup); + action->setCheckable(true); + action->setChecked(al.first == preference); + connect(action, SIGNAL(triggered()), this, SLOT(alignmentTypeChanged())); + if (al.first == Align::NoAlignment) { + menu->addSeparator(); + } + } + + QString program = Align::getPreferredAlignmentProgram(); + if (program == "") { + action = menu->addAction(tr("External Alignment Program")); + action->setEnabled(false); + } else { + QString filename = QFileInfo(program).fileName(); + action = menu->addAction(tr("External Program: %1").arg(filename)); + } + + m_externalAlignmentAction = action; + + action->setObjectName + (Align::getAlignmentTypeTag(Align::ExternalProgramAlignment)); + action->setActionGroup(alignmentGroup); + action->setCheckable(true); + action->setChecked(preference == Align::ExternalProgramAlignment); + connect(action, SIGNAL(triggered()), this, SLOT(alignmentTypeChanged())); + + menu->addSeparator(); + + action = menu->addAction(tr("Choose External Alignment Program...")); + connect(action, SIGNAL(triggered()), this, SLOT(chooseAlignmentProgram())); +} + +void +MainWindow::setupPlaybackMenu() +{ + m_keyReference->setCategory(tr("Playback and Transport Controls")); + + IconLoader il; + + QMenu *menu = menuBar()->addMenu(tr("Play&back")); + menu->setTearOffEnabled(false); + + QToolBar *toolbar = nullptr; + if (m_playbackToolBar) { + toolbar = m_playbackToolBar; + } else { + toolbar = m_playbackToolBar = addToolBar(tr("Playback Toolbar")); + } + + QAction *rwdStartAction = toolbar->addAction(il.load("rewind-start"), + tr("Rewind to Start")); + rwdStartAction->setShortcut(tr("Home")); + rwdStartAction->setStatusTip(tr("Rewind to the start")); + connect(rwdStartAction, SIGNAL(triggered()), this, SLOT(rewindStart())); + connect(this, SIGNAL(canPlay(bool)), rwdStartAction, SLOT(setEnabled(bool))); + + QAction *m_rwdAction = toolbar->addAction(il.load("rewind"), + tr("Rewind")); + m_rwdAction->setShortcut(tr("PgUp")); + m_rwdAction->setStatusTip(tr("Rewind to the previous time instant or time ruler notch")); + connect(m_rwdAction, SIGNAL(triggered()), this, SLOT(rewind())); + connect(this, SIGNAL(canRewind(bool)), m_rwdAction, SLOT(setEnabled(bool))); + + m_playAction = toolbar->addAction(il.load("playpause"), + tr("Play / Pause")); + m_playAction->setCheckable(true); + m_playAction->setShortcut(tr("Space")); + m_playAction->setStatusTip(tr("Start or stop playback from the current position")); + connect(m_playAction, SIGNAL(triggered()), this, SLOT(play())); + connect(m_playSource, SIGNAL(playStatusChanged(bool)), + m_playAction, SLOT(setChecked(bool))); + connect(this, SIGNAL(canPlay(bool)), m_playAction, SLOT(setEnabled(bool))); + + m_ffwdAction = toolbar->addAction(il.load("ffwd"), + tr("Fast Forward")); + m_ffwdAction->setShortcut(tr("PgDown")); + m_ffwdAction->setStatusTip(tr("Fast-forward to the next time instant or time ruler notch")); + connect(m_ffwdAction, SIGNAL(triggered()), this, SLOT(ffwd())); + connect(this, SIGNAL(canFfwd(bool)), m_ffwdAction, SLOT(setEnabled(bool))); + + QAction *ffwdEndAction = toolbar->addAction(il.load("ffwd-end"), + tr("Fast Forward to End")); + ffwdEndAction->setShortcut(tr("End")); + ffwdEndAction->setStatusTip(tr("Fast-forward to the end")); + connect(ffwdEndAction, SIGNAL(triggered()), this, SLOT(ffwdEnd())); + connect(this, SIGNAL(canPlay(bool)), ffwdEndAction, SLOT(setEnabled(bool))); + + QAction *recordAction = toolbar->addAction(il.load("record"), + tr("Record")); + recordAction->setCheckable(true); + recordAction->setShortcut(tr("Ctrl+Space")); + recordAction->setStatusTip(tr("Record a new audio file")); + connect(recordAction, SIGNAL(triggered()), this, SLOT(record())); + connect(m_recordTarget, SIGNAL(recordStatusChanged(bool)), + recordAction, SLOT(setChecked(bool))); + connect(this, SIGNAL(canRecord(bool)), + recordAction, SLOT(setEnabled(bool))); + + m_keyReference->registerShortcut(m_playAction); + m_keyReference->registerShortcut(m_rwdAction); + m_keyReference->registerShortcut(m_ffwdAction); + m_keyReference->registerShortcut(rwdStartAction); + m_keyReference->registerShortcut(ffwdEndAction); + m_keyReference->registerShortcut(recordAction); + + menu->addAction(m_playAction); + menu->addSeparator(); + menu->addAction(m_rwdAction); + menu->addAction(m_ffwdAction); + menu->addSeparator(); + menu->addAction(rwdStartAction); + menu->addAction(ffwdEndAction); + menu->addSeparator(); + menu->addAction(recordAction); + menu->addSeparator(); + + QAction *fastAction = menu->addAction(tr("Speed Up")); + fastAction->setShortcut(tr("Ctrl+PgUp")); + fastAction->setStatusTip(tr("Time-stretch playback to speed it up without changing pitch")); + connect(fastAction, SIGNAL(triggered()), this, SLOT(speedUpPlayback())); + connect(this, SIGNAL(canSpeedUpPlayback(bool)), fastAction, SLOT(setEnabled(bool))); + + QAction *slowAction = menu->addAction(tr("Slow Down")); + slowAction->setShortcut(tr("Ctrl+PgDown")); + slowAction->setStatusTip(tr("Time-stretch playback to slow it down without changing pitch")); + connect(slowAction, SIGNAL(triggered()), this, SLOT(slowDownPlayback())); + connect(this, SIGNAL(canSlowDownPlayback(bool)), slowAction, SLOT(setEnabled(bool))); + + QAction *normalAction = menu->addAction(tr("Restore Normal Speed")); + normalAction->setShortcut(tr("Ctrl+Home")); + normalAction->setStatusTip(tr("Restore non-time-stretched playback")); + connect(normalAction, SIGNAL(triggered()), this, SLOT(restoreNormalPlayback())); + connect(this, SIGNAL(canChangePlaybackSpeed(bool)), normalAction, SLOT(setEnabled(bool))); + + m_keyReference->registerShortcut(fastAction); + m_keyReference->registerShortcut(slowAction); + m_keyReference->registerShortcut(normalAction); +} + +void MainWindow::setupHelpMenu() { QMenu *menu = menuBar()->addMenu(tr("&Help")); @@ -754,158 +955,6 @@ } void -MainWindow::setupRecentSessionsMenu() -{ - m_recentSessionsMenu->clear(); - vector<pair<QString, QString>> sessions = m_recentSessions.getRecentEntries(); - for (size_t i = 0; i < sessions.size(); ++i) { - QString path = sessions[i].first; - QString label = sessions[i].second; - if (label == "") label = path; - QAction *action = new QAction(label, this); - action->setObjectName(path); - connect(action, SIGNAL(triggered()), this, SLOT(openRecentSession())); - if (i == 0) { - action->setShortcut(tr("Ctrl+R")); - m_keyReference->registerShortcut - (tr("Re-open"), - action->shortcut().toString(), - tr("Re-open the current or most recently opened session")); - } - m_recentSessionsMenu->addAction(action); - } -} - -void -MainWindow::setupToolbars() -{ - m_keyReference->setCategory(tr("Playback and Transport Controls")); - - IconLoader il; - - QMenu *menu = m_playbackMenu = menuBar()->addMenu(tr("Play&back")); - menu->setTearOffEnabled(false); - - QToolBar *toolbar = addToolBar(tr("Playback Toolbar")); - - QAction *rwdStartAction = toolbar->addAction(il.load("rewind-start"), - tr("Rewind to Start")); - rwdStartAction->setShortcut(tr("Home")); - rwdStartAction->setStatusTip(tr("Rewind to the start")); - connect(rwdStartAction, SIGNAL(triggered()), this, SLOT(rewindStart())); - connect(this, SIGNAL(canPlay(bool)), rwdStartAction, SLOT(setEnabled(bool))); - - QAction *m_rwdAction = toolbar->addAction(il.load("rewind"), - tr("Rewind")); - m_rwdAction->setShortcut(tr("PgUp")); - m_rwdAction->setStatusTip(tr("Rewind to the previous time instant or time ruler notch")); - connect(m_rwdAction, SIGNAL(triggered()), this, SLOT(rewind())); - connect(this, SIGNAL(canRewind(bool)), m_rwdAction, SLOT(setEnabled(bool))); - - m_playAction = toolbar->addAction(il.load("playpause"), - tr("Play / Pause")); - m_playAction->setCheckable(true); - m_playAction->setShortcut(tr("Space")); - m_playAction->setStatusTip(tr("Start or stop playback from the current position")); - connect(m_playAction, SIGNAL(triggered()), this, SLOT(play())); - connect(m_playSource, SIGNAL(playStatusChanged(bool)), - m_playAction, SLOT(setChecked(bool))); - connect(this, SIGNAL(canPlay(bool)), m_playAction, SLOT(setEnabled(bool))); - - m_ffwdAction = toolbar->addAction(il.load("ffwd"), - tr("Fast Forward")); - m_ffwdAction->setShortcut(tr("PgDown")); - m_ffwdAction->setStatusTip(tr("Fast-forward to the next time instant or time ruler notch")); - connect(m_ffwdAction, SIGNAL(triggered()), this, SLOT(ffwd())); - connect(this, SIGNAL(canFfwd(bool)), m_ffwdAction, SLOT(setEnabled(bool))); - - QAction *ffwdEndAction = toolbar->addAction(il.load("ffwd-end"), - tr("Fast Forward to End")); - ffwdEndAction->setShortcut(tr("End")); - ffwdEndAction->setStatusTip(tr("Fast-forward to the end")); - connect(ffwdEndAction, SIGNAL(triggered()), this, SLOT(ffwdEnd())); - connect(this, SIGNAL(canPlay(bool)), ffwdEndAction, SLOT(setEnabled(bool))); - - QAction *recordAction = toolbar->addAction(il.load("record"), - tr("Record")); - recordAction->setCheckable(true); - recordAction->setShortcut(tr("Ctrl+Space")); - recordAction->setStatusTip(tr("Record a new audio file")); - connect(recordAction, SIGNAL(triggered()), this, SLOT(record())); - connect(m_recordTarget, SIGNAL(recordStatusChanged(bool)), - recordAction, SLOT(setChecked(bool))); - connect(this, SIGNAL(canRecord(bool)), - recordAction, SLOT(setEnabled(bool))); - - m_keyReference->registerShortcut(m_playAction); - m_keyReference->registerShortcut(m_rwdAction); - m_keyReference->registerShortcut(m_ffwdAction); - m_keyReference->registerShortcut(rwdStartAction); - m_keyReference->registerShortcut(ffwdEndAction); - m_keyReference->registerShortcut(recordAction); - - menu->addAction(m_playAction); - menu->addSeparator(); - menu->addAction(m_rwdAction); - menu->addAction(m_ffwdAction); - menu->addSeparator(); - menu->addAction(rwdStartAction); - menu->addAction(ffwdEndAction); - menu->addSeparator(); - menu->addAction(recordAction); - menu->addSeparator(); - - QAction *fastAction = menu->addAction(tr("Speed Up")); - fastAction->setShortcut(tr("Ctrl+PgUp")); - fastAction->setStatusTip(tr("Time-stretch playback to speed it up without changing pitch")); - connect(fastAction, SIGNAL(triggered()), this, SLOT(speedUpPlayback())); - connect(this, SIGNAL(canSpeedUpPlayback(bool)), fastAction, SLOT(setEnabled(bool))); - - QAction *slowAction = menu->addAction(tr("Slow Down")); - slowAction->setShortcut(tr("Ctrl+PgDown")); - slowAction->setStatusTip(tr("Time-stretch playback to slow it down without changing pitch")); - connect(slowAction, SIGNAL(triggered()), this, SLOT(slowDownPlayback())); - connect(this, SIGNAL(canSlowDownPlayback(bool)), slowAction, SLOT(setEnabled(bool))); - - QAction *normalAction = menu->addAction(tr("Restore Normal Speed")); - normalAction->setShortcut(tr("Ctrl+Home")); - normalAction->setStatusTip(tr("Restore non-time-stretched playback")); - connect(normalAction, SIGNAL(triggered()), this, SLOT(restoreNormalPlayback())); - connect(this, SIGNAL(canChangePlaybackSpeed(bool)), normalAction, SLOT(setEnabled(bool))); - - m_keyReference->registerShortcut(fastAction); - m_keyReference->registerShortcut(slowAction); - m_keyReference->registerShortcut(normalAction); - - QAction *alAction = 0; - alAction = toolbar->addAction(il.load("align"), - tr("Align File Timelines")); - alAction->setCheckable(true); - alAction->setChecked(m_viewManager->getAlignMode()); - alAction->setStatusTip(tr("Treat multiple audio files as versions of the same work, and align their timelines")); - connect(m_viewManager, SIGNAL(alignModeChanged(bool)), - alAction, SLOT(setChecked(bool))); - connect(alAction, SIGNAL(triggered()), this, SLOT(alignToggled())); - - QSettings settings; - - QAction *tdAction = 0; - tdAction = new QAction(tr("Allow for Pitch Difference when Aligning"), this); - tdAction->setCheckable(true); - settings.beginGroup("Alignment"); - tdAction->setChecked(settings.value("align-pitch-aware", false).toBool()); - settings.endGroup(); - tdAction->setStatusTip(tr("Compare relative pitch content of audio files before aligning, in order to correctly align recordings of the same material at different tuning pitches")); - connect(tdAction, SIGNAL(triggered()), this, SLOT(tuningDifferenceToggled())); - - menu->addSeparator(); - menu->addAction(alAction); - menu->addAction(tdAction); - - Pane::registerShortcuts(*m_keyReference); -} - -void MainWindow::updateMenuStates() { MainWindowBase::updateMenuStates(); @@ -1414,6 +1463,22 @@ } } +void +MainWindow::mapAllSalientFeatureLayers() +{ + for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { + Pane *p = m_paneStack->getPane(i); + for (int j = 0; j < p->getLayerCount(); ++j) { + auto modelId = p->getLayer(j)->getModel(); + if (auto wfm = ModelById::getAs<WaveFileModel>(modelId)) { + SVDEBUG << "MainWindow::mapAllSalientFeatureLayers: calling mapSalientFeatureLayer for modelId " << modelId << " in pane " << i << ", layer " << j << endl; + mapSalientFeatureLayer(modelId); + break; // but only from inner loop, go on to next pane + } + } + } +} + TimeInstantLayer * MainWindow::findSalientFeatureLayer(Pane *pane) { @@ -1496,17 +1561,13 @@ } void -MainWindow::mapSalientFeatureLayer(ModelId amId) +MainWindow::mapSalientFeatureLayer(ModelId modelId) { - auto am = ModelById::getAs<AlignmentModel>(amId); - if (!am) { - SVCERR << "MainWindow::mapSalientFeatureLayer: AlignmentModel is absent!" - << endl; - return; - } + SVDEBUG << "MainWindow::mapSalientFeatureLayer(" << modelId << ")" << endl; if (m_salientCalculating) { - m_salientPending.insert(amId); + SVDEBUG << "MainWindow::mapSalientFeatureLayer(" << modelId << "): salient still calculating, adding to pending list" << endl; + m_salientPending.insert(modelId); return; } @@ -1514,14 +1575,13 @@ if (!salient) { SVCERR << "MainWindow::mapSalientFeatureLayer: No salient layer found" << endl; - m_salientPending.insert(amId); + m_salientPending.insert(modelId); return; } - ModelId modelId = am->getAlignedModel(); auto model = ModelById::get(modelId); if (!model) { - SVCERR << "MainWindow::mapSalientFeatureLayer: No aligned model in AlignmentModel" << endl; + SVCERR << "MainWindow::mapSalientFeatureLayer: Aligned model is absent" << endl; return; } @@ -1580,14 +1640,24 @@ auto toId = ModelById::add(to); EventVector pp = from->getAllEvents(); - for (const auto &p: pp) { - Event aligned = p - .withFrame(model->alignFromReference(p.getFrame())) - .withLabel(""); // remove label, as the analysis was not - // conducted on the audio we're mapping to - to->add(aligned); + + if (Align::getAlignmentPreference() != Align::NoAlignment) { + for (const auto &p: pp) { + Event aligned = p + .withFrame(model->alignFromReference(p.getFrame())) + .withLabel(""); // remove label, as the analysis was not + // conducted on the audio we're mapping to + to->add(aligned); + } + } else { + for (const auto &p: pp) { + to->add(p.withLabel("")); + } } + SVDEBUG << "MainWindow::mapSalientFeatureLayer for model " << modelId + << ": have " << pp.size() << " events" << endl; + Layer *newLayer = m_document->createImportedLayer(toId); if (newLayer) { @@ -2183,6 +2253,10 @@ zoomToFit(); reselectMode(); + + if (Align::getAlignmentPreference() == Align::NoAlignment) { + mapAllSalientFeatureLayers(); + } } void @@ -2286,23 +2360,40 @@ } void -MainWindow::alignToggled() +MainWindow::alignmentTypeChanged() { QAction *action = dynamic_cast<QAction *>(sender()); - if (!m_viewManager) return; - - if (action) { - m_viewManager->setAlignMode(action->isChecked()); + if (!action || !m_viewManager) return; + + Align::AlignmentType alignmentType = + Align::getAlignmentTypeForTag(action->objectName()); + + if (alignmentType == Align::NoAlignment) { + + Align::setAlignmentPreference(alignmentType); + m_viewManager->setAlignMode(false); + m_document->setAutoAlignment(false); + + SVDEBUG << "MainWindow::alignmentTypeChanged: type is now NoAlignment, so salient feature layer won't be automatically mapped - doing it by hand" << endl; + + mapAllSalientFeatureLayers(); + checkpointSession(); + } else { - m_viewManager->setAlignMode(!m_viewManager->getAlignMode()); - } - - if (m_viewManager->getAlignMode()) { - m_document->alignModels(); + + Align::setAlignmentPreference(alignmentType); + + m_viewManager->setAlignMode(true); + + if (alignmentType == m_previousActiveAlignmentType) { + m_document->alignModels(); + } else { + m_document->realignModels(); + } + m_document->setAutoAlignment(true); - } else { - m_document->setAutoAlignment(false); + m_previousActiveAlignmentType = alignmentType; } for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { @@ -2313,18 +2404,25 @@ } void -MainWindow::tuningDifferenceToggled() +MainWindow::chooseAlignmentProgram() { - QSettings settings; - settings.beginGroup("Alignment"); - bool on = settings.value("align-pitch-aware", false).toBool(); - settings.setValue("align-pitch-aware", !on); - settings.endGroup(); - - if (m_viewManager->getAlignMode()) { - m_document->realignModels(); + QString formerProgram = Align::getPreferredAlignmentProgram(); + QString newProgram = + QFileDialog::getOpenFileName(this, + tr("External Alignment Program"), + formerProgram); + if (newProgram != "") { + SVCERR << "Setting alignment preference to ExternalProgramAlignment " + << "with program " << newProgram << endl; + Align::setAlignmentPreference(Align::ExternalProgramAlignment); + Align::setPreferredAlignmentProgram(newProgram); + QString filename = QFileInfo(newProgram).fileName(); + m_externalAlignmentAction->setText + (tr("External Program: %1").arg(filename)); + m_externalAlignmentAction->setEnabled(true); + m_externalAlignmentAction->activate(QAction::Trigger); } -} +} void MainWindow::playSpeedChanged(int position) @@ -2877,9 +2975,17 @@ } void -MainWindow::alignmentComplete(ModelId modelId) +MainWindow::alignmentComplete(ModelId amId) { - cerr << "MainWindow::alignmentComplete(" << modelId << ")" << endl; + SVCERR << "MainWindow::alignmentComplete(" << amId << ")" << endl; + auto am = ModelById::getAs<AlignmentModel>(amId); + if (!am) { + SVCERR << "MainWindow::alignmentComplete: AlignmentModel is absent!" + << endl; + return; + } + + ModelId modelId = am->getAlignedModel(); mapSalientFeatureLayer(modelId); checkpointSession(); }
--- a/main/MainWindow.h Thu May 14 16:59:51 2020 +0100 +++ b/main/MainWindow.h Fri Jun 26 13:52:26 2020 +0100 @@ -30,6 +30,7 @@ #include "transform/Transform.h" #include "framework/SVFileReader.h" #include "widgets/InteractiveFileFinder.h" +#include "align/Align.h" #include "SmallSession.h" @@ -122,14 +123,14 @@ void paneDropAccepted(Pane *, QString) override; void record() override; - - virtual void alignToggled(); - virtual void tuningDifferenceToggled(); - virtual void playSpeedChanged(int); - virtual void speedUpPlayback(); - virtual void slowDownPlayback(); - virtual void restoreNormalPlayback(); + void alignmentTypeChanged(); + void chooseAlignmentProgram(); + + void playSpeedChanged(int); + void speedUpPlayback(); + void slowDownPlayback(); + void restoreNormalPlayback(); void monitoringLevelsChanged(float, float) override; @@ -192,7 +193,7 @@ QScrollArea *m_mainScroll; bool m_mainMenusCreated; - QMenu *m_playbackMenu; + QToolBar *m_playbackToolBar; QMenu *m_recentSessionsMenu; QAction *m_deleteSelectedAction; @@ -211,6 +212,9 @@ QAction *m_selectPreviousDisplayModeAction; QAction *m_selectNextDisplayModeAction; + QAction *m_externalAlignmentAction; + Align::AlignmentType m_previousActiveAlignmentType; + RecentFiles m_recentSessions; bool m_exiting; @@ -232,8 +236,9 @@ virtual void setupFileMenu(); virtual void setupViewMenu(); + virtual void setupAlignmentMenu(); + virtual void setupPlaybackMenu(); virtual void setupHelpMenu(); - virtual void setupToolbars(); enum DisplayMode { OutlineWaveformMode, @@ -265,7 +270,9 @@ ModelId *createFrom); virtual void addSalientFeatureLayer(Pane *, ModelId); // a WaveFileModel - virtual void mapSalientFeatureLayer(ModelId); // an AlignmentModel + virtual void mapSalientFeatureLayer(ModelId); // a WaveFileModel + + void mapAllSalientFeatureLayers(); // Return the salient-feature layer in the given pane. If pane is // unspecified, return the main salient-feature layer, i.e. the @@ -274,7 +281,7 @@ virtual TimeInstantLayer *findSalientFeatureLayer(Pane *pane = nullptr); bool m_salientCalculating; - std::set<ModelId> m_salientPending; // AlignmentModels + std::set<ModelId> m_salientPending; // Aligned WaveFileModels int m_salientColour; void updateVisibleRangeDisplay(Pane *p) const override;
--- a/pitch-track-align/pitch-track-align.sml Thu May 14 16:59:51 2020 +0100 +++ b/pitch-track-align/pitch-track-align.sml Fri Jun 26 13:52:26 2020 +0100 @@ -70,6 +70,16 @@ fun alignSeries s1 s2 = let val cumulativeCosts = costSeries s1 s2 +(* val _ = let open TextIO in + output (stdErr, "Cost matrix:\n"); + Vector.app + (fn v => + (Vector.app + (fn x => output (stdErr, Real.toString x ^ " ")) v; + output (stdErr, "\n"))) + cumulativeCosts + end +*) fun cost (j, i) = Vector.sub (Vector.sub (cumulativeCosts, j), i) fun trace (j, i) acc = if i = 0 @@ -123,7 +133,7 @@ in rev (#1 acc) end - val _ = +(* val _ = app (fn (text, p) => TextIO.output (TextIO.stdErr, ("[" ^ text ^ "] -> " ^ Real.toString p ^ "\n"))) @@ -131,6 +141,18 @@ | (PITCH_UP d, p) => ("+", p) | (PITCH_DOWN d, p) => ("-", p)) (values, pitches)) + val _ = TextIO.output (TextIO.stdErr, "(end)\n"); + *) + val _ = + app (fn v => + TextIO.output (TextIO.stdErr, + (case v of + PITCH_NONE => "=0" + | PITCH_UP d => "+" ^ Real.toString d + | PITCH_DOWN d => "-" ^ Real.toString d) + ^ " ")) + values + val _ = TextIO.output (TextIO.stdErr, " (end)\n"); in (Vector.fromList times, Vector.fromList values, @@ -181,6 +203,11 @@ (* raw alignment returns the index into pitches2 for each element in pitches1 *) val raw = alignSeries values1 values2 + val _ = TextIO.output (TextIO.stdErr, "DTW output:\n") + val _ = Vector.app + (fn i => TextIO.output (TextIO.stdErr, Int.toString i ^ " ")) + raw + val _ = TextIO.output (TextIO.stdErr, "\n") val _ = TextIO.output (TextIO.stdErr, "Mean pitch difference: reference " ^ Real.toString (meanDiff pitches1 pitches2 raw)
--- a/repoint-lock.json Thu May 14 16:59:51 2020 +0100 +++ b/repoint-lock.json Fri Jun 26 13:52:26 2020 +0100 @@ -1,16 +1,16 @@ { "libraries": { "vamp-plugin-sdk": { - "pin": "8ffb8985ae8f" + "pin": "0e32c328b02a" }, "svcore": { - "pin": "14747f24ad04" + "pin": "38be2fa29efd" }, "svgui": { - "pin": "bd1a7c84da8c" + "pin": "fe9a643b83bf" }, "svapp": { - "pin": "cf4e0f3c2406" + "pin": "83a7b10b7415" }, "checker": { "pin": "e839338d3869" @@ -70,7 +70,7 @@ "pin": "e34a3cc188332ed7c33cd9257ef164de5b587191" }, "azi": { - "pin": "d490c1c7e1ae" + "pin": "299df1b44eff" } } }
