changeset 237:63092d9871f9

Add command to snap notes back to pitch track median on request; add split at selection boundaries
author Chris Cannam
date Thu, 27 Mar 2014 15:59:46 +0000
parents 389ed196d23b
children fce61899aeea
files .hgsubstate src/MainWindow.cpp src/MainWindow.h
diffstat 3 files changed, 84 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsubstate	Tue Mar 25 13:06:27 2014 +0000
+++ b/.hgsubstate	Thu Mar 27 15:59:46 2014 +0000
@@ -4,4 +4,4 @@
 27d4e7152c954bf3c4387319db088fb3cd02436b sv-dependency-builds
 3144af512ea3447e6cf1775f02b5b54b5a5ddeb5 svapp
 0c8218b2d84a172049d966c82c2064f5aa59c503 svcore
-d50f91fe374e7799be924e05f0811e158cb8ef73 svgui
+8d5df70b5ed703ade1b382744dad24e3841157e9 svgui
--- a/src/MainWindow.cpp	Tue Mar 25 13:06:27 2014 +0000
+++ b/src/MainWindow.cpp	Thu Mar 27 15:59:46 2014 +0000
@@ -587,6 +587,27 @@
     connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool)));
     menu->addAction(action);
     m_rightButtonMenu->addAction(action);
+
+    menu->addSeparator();
+    m_rightButtonMenu->addSeparator();
+    
+    action = new QAction(tr("Snap Notes to Pitch Track"), this);
+    action->setShortcut(tr("Ctrl+="));
+    action->setStatusTip(tr("Set all notes within the selected region to have the median frequency of their underlying pitches"));
+    m_keyReference->registerShortcut(action);
+    connect(action, SIGNAL(triggered()), this, SLOT(snapNotesToPitches()));
+    connect(this, SIGNAL(canSnapNotes(bool)), action, SLOT(setEnabled(bool)));
+    menu->addAction(action);
+    m_rightButtonMenu->addAction(action);
+    
+    action = new QAction(tr("Split Notes at Selection Boundaries"), this);
+    action->setShortcut(tr("Ctrl+/"));
+    action->setStatusTip(tr("If any notes overlap the start or end of the selected region, split them at those points"));
+    m_keyReference->registerShortcut(action);
+    connect(action, SIGNAL(triggered()), this, SLOT(splitNotesAtSelection()));
+    connect(this, SIGNAL(canSnapNotes(bool)), action, SLOT(setEnabled(bool)));
+    menu->addAction(action);
+    m_rightButtonMenu->addAction(action);
 }
 
 void
@@ -1068,10 +1089,17 @@
     emit canSpeedUpPlayback(v < m_playSpeed->maximum());
     emit canSlowDownPlayback(v > m_playSpeed->minimum());
 
-    emit canExportPitchTrack(m_analyser->isVisible(Analyser::PitchTrack) &&
-                             m_analyser->getLayer(Analyser::PitchTrack));
-    emit canExportNotes(m_analyser->isVisible(Analyser::Notes) &&
-                        m_analyser->getLayer(Analyser::Notes));
+    bool havePitchTrack = 
+        m_analyser->isVisible(Analyser::PitchTrack) &&
+        m_analyser->getLayer(Analyser::PitchTrack);
+
+    bool haveNotes = 
+        m_analyser->isVisible(Analyser::Notes) &&
+        m_analyser->getLayer(Analyser::Notes);
+
+    emit canExportPitchTrack(havePitchTrack);
+    emit canExportNotes(haveNotes);
+    emit canSnapNotes(haveSelection && haveNotes);
 
     if (pitchCandidatesVisible) {
         m_showCandidatesAction->setText(tr("Hide Pitch Candidates"));
@@ -2019,6 +2047,53 @@
 }
 
 void
+MainWindow::snapNotesToPitches()
+{
+    FlexiNoteLayer *layer =
+        qobject_cast<FlexiNoteLayer *>(m_analyser->getLayer(Analyser::Notes));
+    if (!layer) return;
+
+    MultiSelection::SelectionList selections = m_viewManager->getSelections();
+
+    if (!selections.empty()) {
+
+        CommandHistory::getInstance()->startCompoundOperation
+            (tr("Snap Notes to Pitches"), true);
+                
+        for (MultiSelection::SelectionList::iterator k = selections.begin();
+             k != selections.end(); ++k) {
+            layer->snapSelectedNotesToPitchTrack(m_analyser->getPane(), *k);
+        }
+        
+        CommandHistory::getInstance()->endCompoundOperation();
+    }
+}
+
+void
+MainWindow::splitNotesAtSelection()
+{
+    FlexiNoteLayer *layer =
+        qobject_cast<FlexiNoteLayer *>(m_analyser->getLayer(Analyser::Notes));
+    if (!layer) return;
+
+    MultiSelection::SelectionList selections = m_viewManager->getSelections();
+
+    if (!selections.empty()) {
+
+        CommandHistory::getInstance()->startCompoundOperation
+            (tr("Split Notes at Selection Boundaries"), true);
+                
+        for (MultiSelection::SelectionList::iterator k = selections.begin();
+             k != selections.end(); ++k) {
+            layer->splitNotesAt(m_analyser->getPane(), k->getStartFrame());
+            layer->splitNotesAt(m_analyser->getPane(), k->getEndFrame());
+        }
+        
+        CommandHistory::getInstance()->endCompoundOperation();
+    }
+}
+
+void
 MainWindow::playSpeedChanged(int position)
 {
     PlaySpeedRangeMapper mapper(0, 200);
--- a/src/MainWindow.h	Tue Mar 25 13:06:27 2014 +0000
+++ b/src/MainWindow.h	Thu Mar 27 15:59:46 2014 +0000
@@ -33,6 +33,7 @@
 signals:
     virtual void canExportPitchTrack(bool);
     virtual void canExportNotes(bool);
+    virtual void canSnapNotes(bool);
 
 public slots:
     virtual bool commitData(bool mayAskUser); // on session shutdown
@@ -58,6 +59,9 @@
     virtual void switchPitchUp();
     virtual void switchPitchDown();
 
+    virtual void snapNotesToPitches();
+    virtual void splitNotesAtSelection();
+
     virtual void showAudioToggled();
     virtual void showSpectToggled();
     virtual void showPitchToggled();