diff layer/FlexiNoteLayer.cpp @ 746:8d5df70b5ed7 tonioni

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 d50f91fe374e
children bc049f1f080e
line wrap: on
line diff
--- a/layer/FlexiNoteLayer.cpp	Tue Mar 25 13:06:27 2014 +0000
+++ b/layer/FlexiNoteLayer.cpp	Thu Mar 27 15:59:46 2014 +0000
@@ -1214,11 +1214,18 @@
         return; 
     }
 
-    // MM: simpler declaration 
-    FlexiNote note(0);
-    if (!getPointToDrag(v, e->x(), e->y(), note)) return;
+    long frame = v->getFrameForX(e->x());
 
-    long frame = v->getFrameForX(e->x());
+    splitNotesAt(v, frame);
+}
+
+void
+FlexiNoteLayer::splitNotesAt(View *v, int frame)
+{
+    FlexiNoteModel::PointList onPoints = m_model->getPoints(frame);
+    if (onPoints.empty()) return;
+    
+    FlexiNote note(*onPoints.begin());
 
     int gap = 0; // MM: I prefer a gap of 0, but we can decide later
     
@@ -1239,14 +1246,16 @@
     FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand
         (m_model, tr("Edit Point"));
     command->deletePoint(note);
+
+/* cc can this be the best way to delete a note?
     if ((e->modifiers() & Qt::ShiftModifier)) {
         finish(command);
         return;
     }
+*/
     command->addPoint(newNote1);
     command->addPoint(newNote2);
     finish(command);
-    
 }
 
 void
@@ -1276,8 +1285,7 @@
     }
 
     if (!m_intelligentActions || 
-        m_model->getPoints(frame).empty() && duration > 0)
-    {
+        (m_model->getPoints(frame).empty() && duration > 0)) {
         FlexiNote newNote(frame, value, duration, 100, "new note");
         FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand
             (m_model, tr("Add Point"));
@@ -1291,12 +1299,17 @@
 {
     // Better than we used to do, but still not very satisfactory
 
+    cerr << "FlexiNoteLayer::getAssociatedPitchModel()" << endl;
+
     for (int i = 0; i < v->getLayerCount(); ++i) {
         Layer *layer = v->getLayer(i);
-        if (layer) {
+        if (layer && !layer->isLayerDormant(v)) {
+            cerr << "FlexiNoteLayer::getAssociatedPitchModel: looks like our layer is " << layer << endl;
             SparseTimeValueModel *model = qobject_cast<SparseTimeValueModel *>
                 (layer->getModel());
+            cerr << "FlexiNoteLayer::getAssociatedPitchModel: and its model is " << model << endl;
             if (model && model->getScaleUnits() == "Hz") {
+                cerr << "FlexiNoteLayer::getAssociatedPitchModel: it's good, returning " << model << endl;
                 return model;
             }
         }
@@ -1305,6 +1318,43 @@
 }
 
 void
+FlexiNoteLayer::snapSelectedNotesToPitchTrack(View *v, Selection s)
+{
+    if (!m_model) return;
+
+    FlexiNoteModel::PointList points =
+        m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand
+        (m_model, tr("Snap Notes"));
+
+    cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl;
+
+    for (FlexiNoteModel::PointList::iterator i = points.begin();
+         i != points.end(); ++i) {
+
+        FlexiNote note(*i);
+
+        cerr << "snapSelectedNotesToPitchTrack: looking at note from " << note.frame << " to " << note.frame + note.duration << endl;
+
+        if (!s.contains(note.frame) ||
+            !s.contains(note.frame + note.duration - 1)) {
+            continue;
+        }
+
+        FlexiNote newNote(note);
+
+        command->deletePoint(note);
+
+        updateNoteValue(v, newNote);
+
+        command->addPoint(newNote);
+    }
+
+    finish(command);
+}
+
+void
 FlexiNoteLayer::updateNoteValue(View *v, FlexiNoteModel::Point &note) const
 {
     SparseTimeValueModel *model = getAssociatedPitchModel(v);
@@ -1313,10 +1363,11 @@
     std::cerr << model->getTypeName() << std::endl;
 
     SparseModel<TimeValuePoint>::PointList dataPoints = model->getPoints(note.frame, note.frame + note.duration);
+   
+    std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl;
+   
     if (dataPoints.empty()) return;
-   
-    // std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl;
-   
+
     std::vector<float> pitchValues;
    
     for (SparseModel<TimeValuePoint>::PointList::const_iterator i = dataPoints.begin();