changeset 167:6b6906017536

Choose a different pitch candidate within selection by hitting Return
author Chris Cannam
date Mon, 03 Feb 2014 17:04:03 +0000
parents ebcfb8dce020
children c5e4eaeb9a27
files src/Analyser.cpp src/Analyser.h src/MainWindow.cpp src/MainWindow.h
diffstat 4 files changed, 151 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/src/Analyser.cpp	Fri Jan 31 17:54:49 2014 +0000
+++ b/src/Analyser.cpp	Mon Feb 03 17:04:03 2014 +0000
@@ -74,6 +74,7 @@
 
     m_reAnalysingSelection = Selection();
     m_reAnalysisCandidates.clear();
+    m_currentCandidate = -1;
 
     // Note that we need at least one main-model layer (time ruler,
     // waveform or what have you). It could be hidden if we don't want
@@ -136,6 +137,7 @@
     spectrogram->setNormalizeHybrid(true);
 //    spectrogram->setSmooth(true);
 //    spectrogram->setGain(0.5); //!!! arbitrary at this point
+    spectrogram->setMinFrequency(15);
     spectrogram->setGain(100);
     m_document->addLayerToView(m_pane, spectrogram);
     spectrogram->setLayerDormant(m_pane, true);
@@ -250,12 +252,8 @@
 {
     if (sel == m_reAnalysingSelection) return "";
 
-    foreach (Layer *layer, m_reAnalysisCandidates) {
-        cerr << "deleting previous candidate layer " << layer << endl;
-        m_pane->removeLayer(layer);
-        m_document->deleteLayer(layer); // also releases its model
-    }
-    m_reAnalysisCandidates.clear();
+    clearReAnalysis();
+
     m_reAnalysingSelection = sel;
 
     TransformFactory *tf = TransformFactory::getInstance();
@@ -305,17 +303,23 @@
     //!!! how do we know these came from the right selection? user
     //!!! might have made another one since this request was issued
 
+    vector<Layer *> all;
     for (int i = 0; i < (int)primary.size(); ++i) {
-        TimeValueLayer *t = qobject_cast<TimeValueLayer *>(primary[i]);
-        if (t) {
-            m_document->addLayerToView(m_pane, t);
-            m_reAnalysisCandidates.push_back(t);
-        }
+        all.push_back(primary[i]);
+    }
+    for (int i = 0; i < (int)additional.size(); ++i) {
+        all.push_back(additional[i]);
     }
 
-    for (int i = 0; i < (int)additional.size(); ++i) {
-        TimeValueLayer *t = qobject_cast<TimeValueLayer *>(additional[i]);
+    for (int i = 0; i < (int)all.size(); ++i) {
+        TimeValueLayer *t = qobject_cast<TimeValueLayer *>(all[i]);
         if (t) {
+            PlayParameters *params = t->getPlayParameters();
+            if (params) {
+                params->setPlayAudible(false);
+            }
+            t->setBaseColour
+                (ColourDatabase::getInstance()->getColourIndex(tr("Bright Orange")));
             m_document->addLayerToView(m_pane, t);
             m_reAnalysisCandidates.push_back(t);
         }
@@ -323,6 +327,55 @@
 }
 
 void
+Analyser::switchPitchCandidate(Selection sel, bool up)
+{
+    if (m_reAnalysisCandidates.empty()) return;
+
+    if (up) {
+        m_currentCandidate = m_currentCandidate + 1;
+        if (m_currentCandidate >= m_reAnalysisCandidates.size()) {
+            m_currentCandidate = 0;
+        }
+    } else {
+        m_currentCandidate = m_currentCandidate - 1;
+        if (m_currentCandidate < 0) {
+            m_currentCandidate = m_reAnalysisCandidates.size() - 1;
+        }
+    }
+
+    Layer *pitchTrack = m_layers[PitchTrack];
+    if (!pitchTrack) return;
+
+    CommandHistory::getInstance()->startCompoundOperation
+        (tr("Switch Pitch Candidate"), true);
+
+    Clipboard clip;
+    pitchTrack->deleteSelection(sel);
+    m_reAnalysisCandidates[m_currentCandidate]->copy(m_pane, sel, clip);
+    pitchTrack->paste(m_pane, clip, 0, false);
+
+    CommandHistory::getInstance()->endCompoundOperation();
+
+    // raise the pitch track, then notes on top (if present)
+    m_paneStack->setCurrentLayer(m_pane, m_layers[PitchTrack]);
+    if (m_layers[Notes] && !m_layers[Notes]->isLayerDormant(m_pane)) {
+        m_paneStack->setCurrentLayer(m_pane, m_layers[Notes]);
+    }
+}
+
+void
+Analyser::clearReAnalysis()
+{
+    foreach (Layer *layer, m_reAnalysisCandidates) {
+        m_pane->removeLayer(layer);
+        m_document->deleteLayer(layer); // also releases its model
+    }
+    m_reAnalysisCandidates.clear();
+    m_reAnalysingSelection = Selection();
+    m_currentCandidate = -1;
+}    
+
+void
 Analyser::getEnclosingSelectionScope(size_t f, size_t &f0, size_t &f1)
 {
     FlexiNoteLayer *flexiNoteLayer = 
@@ -396,8 +449,17 @@
     if (m_layers[c]) {
         m_layers[c]->setLayerDormant(m_pane, !v);
 
-        if (v && (c == Notes)) {
-            m_paneStack->setCurrentLayer(m_pane, m_layers[c]);
+        if (v) {
+            if (c == Notes) {
+                m_paneStack->setCurrentLayer(m_pane, m_layers[c]);
+            } else if (c == PitchTrack) {
+                // raise the pitch track, then notes on top (if present)
+                m_paneStack->setCurrentLayer(m_pane, m_layers[c]);
+                if (m_layers[Notes] &&
+                    !m_layers[Notes]->isLayerDormant(m_pane)) {
+                    m_paneStack->setCurrentLayer(m_pane, m_layers[Notes]);
+                }
+            }
         }
 
         m_pane->layerParametersChanged();
--- a/src/Analyser.h	Fri Jan 31 17:54:49 2014 +0000
+++ b/src/Analyser.h	Mon Feb 03 17:04:03 2014 +0000
@@ -90,6 +90,18 @@
      */
     QString reAnalyseSelection(Selection sel);
 
+    /**
+     * If a re-analysis has been activated, switch the selected area
+     * of the main pitch track to a different candidate from the
+     * analysis results.
+     */
+    void switchPitchCandidate(Selection sel, bool up);
+
+    /**
+     * Remove any re-analysis layers.
+     */
+    void clearReAnalysis();
+
 signals:
     void layersChanged();
 
@@ -103,6 +115,7 @@
 
     Selection m_reAnalysingSelection;
     std::vector<Layer *> m_reAnalysisCandidates;
+    int m_currentCandidate;
 
     QString addVisualisations();
     QString addWaveform();
--- a/src/MainWindow.cpp	Fri Jan 31 17:54:49 2014 +0000
+++ b/src/MainWindow.cpp	Mon Feb 03 17:04:03 2014 +0000
@@ -536,6 +536,13 @@
     connect(action, SIGNAL(triggered()), this, SLOT(octaveShiftDown()));
     connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool)));
     menu->addAction(action);
+    
+    //!!! shortcuts, status tip, key reference etc
+    action = new QAction(tr("Switch Pitch Candidate"), this);
+    action->setShortcut(tr("Return"));
+    connect(action, SIGNAL(triggered()), this, SLOT(switchPitchUp()));
+    connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool)));
+    menu->addAction(action);
 }
 
 void
@@ -1119,29 +1126,29 @@
 
     while (m_paneStack->getPaneCount() > 0) {
 
-    Pane *pane = m_paneStack->getPane(m_paneStack->getPaneCount() - 1);
+        Pane *pane = m_paneStack->getPane(m_paneStack->getPaneCount() - 1);
 
-    while (pane->getLayerCount() > 0) {
-        m_document->removeLayerFromView
-        (pane, pane->getLayer(pane->getLayerCount() - 1));
-    }
-
-    m_overview->unregisterView(pane);
-    m_paneStack->deletePane(pane);
+        while (pane->getLayerCount() > 0) {
+            m_document->removeLayerFromView
+                (pane, pane->getLayer(pane->getLayerCount() - 1));
+        }
+        
+        m_overview->unregisterView(pane);
+        m_paneStack->deletePane(pane);
     }
 
     while (m_paneStack->getHiddenPaneCount() > 0) {
 
-    Pane *pane = m_paneStack->getHiddenPane
-        (m_paneStack->getHiddenPaneCount() - 1);
-
-    while (pane->getLayerCount() > 0) {
-        m_document->removeLayerFromView
-        (pane, pane->getLayer(pane->getLayerCount() - 1));
-    }
-
-    m_overview->unregisterView(pane);
-    m_paneStack->deletePane(pane);
+        Pane *pane = m_paneStack->getHiddenPane
+            (m_paneStack->getHiddenPaneCount() - 1);
+        
+        while (pane->getLayerCount() > 0) {
+            m_document->removeLayerFromView
+                (pane, pane->getLayer(pane->getLayerCount() - 1));
+        }
+        
+        m_overview->unregisterView(pane);
+        m_paneStack->deletePane(pane);
     }
 
     delete m_document;
@@ -1631,6 +1638,15 @@
 }
 
 void
+MainWindow::clearSelection()
+{
+    cerr << "MainWindow::clearSelection()" << endl;
+
+    m_analyser->clearReAnalysis();
+    MainWindowBase::clearSelection();
+}
+
+void
 MainWindow::selectionChanged()
 {
     MultiSelection::SelectionList selections = m_viewManager->getSelections();
@@ -1664,6 +1680,8 @@
 void
 MainWindow::octaveShift(bool up)
 {
+    // Should this be in the Analyser?
+
     float factor = (up ? 2.f : 0.5f);
 
     MultiSelection::SelectionList selections = m_viewManager->getSelections();
@@ -1707,6 +1725,28 @@
 }
 
 void
+MainWindow::switchPitchUp()
+{
+    MultiSelection::SelectionList selections = m_viewManager->getSelections();
+
+    for (MultiSelection::SelectionList::iterator k = selections.begin();
+         k != selections.end(); ++k) {
+        m_analyser->switchPitchCandidate(*k, true);
+    }
+}
+
+void
+MainWindow::switchPitchDown()
+{
+    MultiSelection::SelectionList selections = m_viewManager->getSelections();
+
+    for (MultiSelection::SelectionList::iterator k = selections.begin();
+         k != selections.end(); ++k) {
+        m_analyser->switchPitchCandidate(*k, false);
+    }
+}
+
+void
 MainWindow::playSpeedChanged(int position)
 {
     PlaySpeedRangeMapper mapper(0, 200);
--- a/src/MainWindow.h	Fri Jan 31 17:54:49 2014 +0000
+++ b/src/MainWindow.h	Mon Feb 03 17:04:03 2014 +0000
@@ -52,6 +52,8 @@
 
     virtual void octaveShiftUp();
     virtual void octaveShiftDown();
+    virtual void switchPitchUp();
+    virtual void switchPitchDown();
 
     virtual void showAudioToggled();
     virtual void showSpectToggled();
@@ -63,6 +65,7 @@
     virtual void playNotesToggled();
 
     virtual void doubleClickSelectInvoked(size_t);
+    virtual void clearSelection();
 
     virtual void paneAdded(Pane *);
     virtual void paneHidden(Pane *);