Mercurial > hg > sonic-lineup
changeset 427:5dc6605f0db2 pitch-align
Alignment menu, and a start on implementing its contents
| author | Chris Cannam |
|---|---|
| date | Thu, 21 May 2020 16:23:33 +0100 |
| parents | be13a41ed469 |
| children | 213fb6c6a426 |
| files | main/MainWindow.cpp main/MainWindow.h repoint-project.json |
| diffstat | 3 files changed, 248 insertions(+), 195 deletions(-) [+] |
line wrap: on
line diff
--- a/main/MainWindow.cpp Tue May 19 09:28:15 2020 +0100 +++ b/main/MainWindow.cpp Thu May 21 16:23:33 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" @@ -135,11 +137,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 +383,6 @@ mainFrame->setLayout(mainLayout); setupMenus(); - setupToolbars(); - setupHelpMenu(); statusBar()->hide(); @@ -416,11 +417,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 +554,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 +747,179 @@ } void +MainWindow::setupAlignmentMenu() +{ + m_keyReference->setCategory(tr("Alignment")); + + IconLoader il; + + QMenu *menu = menuBar()->addMenu(tr("&Alignment")); + menu->setTearOffEnabled(false); + +/*!!! update: + + QToolBar *toolbar = nullptr; + if (m_playbackToolBar) { + toolbar = m_playbackToolBar; + } else { + toolbar = m_playbackToolBar = addToolBar(tr("Playback Toolbar")); + } + + 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())); + + menu->addAction(alAction); +*/ +// MenuTitle::addSection(menu, tr("Alignment Method")); + + QSettings settings; + + 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("Online DTW (MATCH)") }, + { Align::MATCHAlignmentWithPitchCompare, tr("Online DTW with Pitch Compensation") }, + { Align::SungPitchContourAlignment, tr("Sung Pitch Contour") } + }; + + QAction *action = nullptr; + QString additionalData; + Align::AlignmentType preference = + Align::getAlignmentPreference(additionalData); + + 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(); + } + } +} + +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 +958,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(); @@ -2286,23 +2338,34 @@ } 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()); + + Align::setAlignmentPreference(alignmentType); + + if (alignmentType == Align::NoAlignment) { + + m_viewManager->setAlignMode(false); + m_document->setAutoAlignment(false); + } else { - m_viewManager->setAlignMode(!m_viewManager->getAlignMode()); - } - - if (m_viewManager->getAlignMode()) { - m_document->alignModels(); + + 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) { @@ -2311,20 +2374,6 @@ pane->update(); } } - -void -MainWindow::tuningDifferenceToggled() -{ - 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(); - } -} void MainWindow::playSpeedChanged(int position) @@ -2879,7 +2928,7 @@ void MainWindow::alignmentComplete(ModelId modelId) { - cerr << "MainWindow::alignmentComplete(" << modelId << ")" << endl; + SVCERR << "MainWindow::alignmentComplete(" << modelId << ")" << endl; mapSalientFeatureLayer(modelId); checkpointSession(); }
--- a/main/MainWindow.h Tue May 19 09:28:15 2020 +0100 +++ b/main/MainWindow.h Thu May 21 16:23:33 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,13 @@ 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 playSpeedChanged(int); + void speedUpPlayback(); + void slowDownPlayback(); + void restoreNormalPlayback(); void monitoringLevelsChanged(float, float) override; @@ -192,7 +192,7 @@ QScrollArea *m_mainScroll; bool m_mainMenusCreated; - QMenu *m_playbackMenu; + QToolBar *m_playbackToolBar; QMenu *m_recentSessionsMenu; QAction *m_deleteSelectedAction; @@ -211,6 +211,8 @@ QAction *m_selectPreviousDisplayModeAction; QAction *m_selectNextDisplayModeAction; + Align::AlignmentType m_previousActiveAlignmentType; + RecentFiles m_recentSessions; bool m_exiting; @@ -232,8 +234,9 @@ virtual void setupFileMenu(); virtual void setupViewMenu(); + virtual void setupAlignmentMenu(); + virtual void setupPlaybackMenu(); virtual void setupHelpMenu(); - virtual void setupToolbars(); enum DisplayMode { OutlineWaveformMode,
