changeset 747:bc049f1f080e tonioni

Add Merge Notes
author Chris Cannam
date Thu, 27 Mar 2014 16:30:26 +0000
parents 8d5df70b5ed7
children 84e4cf889659
files layer/FlexiNoteLayer.cpp layer/FlexiNoteLayer.h
diffstat 2 files changed, 65 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/layer/FlexiNoteLayer.cpp	Thu Mar 27 15:59:46 2014 +0000
+++ b/layer/FlexiNoteLayer.cpp	Thu Mar 27 16:30:26 2014 +0000
@@ -1229,7 +1229,6 @@
 
     int gap = 0; // MM: I prefer a gap of 0, but we can decide later
     
-    // MM: changed this a bit, to make it slightly clearer (// GF: nice changes!)
     FlexiNote newNote1(note.frame, note.value, 
                        frame - note.frame - gap, 
                        note.level, note.label);
@@ -1237,24 +1236,23 @@
     FlexiNote newNote2(frame, note.value, 
                        note.duration - newNote1.duration, 
                        note.level, note.label);
-                       
-    if (m_intelligentActions) {
-        updateNoteValue(v,newNote1);
-        updateNoteValue(v,newNote2);
-    }
 
     FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand
         (m_model, tr("Edit Point"));
     command->deletePoint(note);
+                       
+    if (m_intelligentActions) {
+        if (updateNoteValue(v, newNote1)) {
+            command->addPoint(newNote1);
+        }
+        if (updateNoteValue(v, newNote2)) {
+            command->addPoint(newNote2);
+        }
+    } else {
+        command->addPoint(newNote1);
+        command->addPoint(newNote2);
+    }
 
-/* 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);
 }
 
@@ -1346,34 +1344,73 @@
 
         command->deletePoint(note);
 
-        updateNoteValue(v, newNote);
-
-        command->addPoint(newNote);
+        if (updateNoteValue(v, newNote)) {
+            command->addPoint(newNote);
+        }
     }
-
+    
     finish(command);
 }
 
 void
+FlexiNoteLayer::mergeNotes(View *v, Selection s)
+{
+    FlexiNoteModel::PointList points =
+        m_model->getPoints(s.getStartFrame(), s.getEndFrame());
+
+    FlexiNoteModel::PointList::iterator i = points.begin();
+    while (i != points.end() && i->frame + i->duration < s.getStartFrame()) {
+        ++i;
+    }
+    if (i == points.end()) return;
+
+    FlexiNoteModel::EditCommand *command = 
+        new FlexiNoteModel::EditCommand(m_model, tr("Merge Notes"));
+
+    FlexiNote newNote(*i);
+
+    while (i != points.end()) {
+
+        if (i->frame >= s.getEndFrame()) break;
+
+        newNote.duration = i->frame + i->duration - newNote.frame;
+        command->deletePoint(*i);
+
+        ++i;
+    }
+
+    updateNoteValue(v, newNote);
+    command->addPoint(newNote);
+    finish(command);
+}
+
+bool
 FlexiNoteLayer::updateNoteValue(View *v, FlexiNoteModel::Point &note) const
 {
     SparseTimeValueModel *model = getAssociatedPitchModel(v);
-    if (!model) return;
+    if (!model) return false;
         
     std::cerr << model->getTypeName() << std::endl;
 
-    SparseModel<TimeValuePoint>::PointList dataPoints = model->getPoints(note.frame, note.frame + note.duration);
+    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;
+    if (dataPoints.empty()) return false;
 
     std::vector<float> pitchValues;
    
-    for (SparseModel<TimeValuePoint>::PointList::const_iterator i = dataPoints.begin(); 
-         i != dataPoints.end(); ++i) {
-        pitchValues.push_back((*i).value);
+    for (SparseModel<TimeValuePoint>::PointList::const_iterator i =
+             dataPoints.begin(); i != dataPoints.end(); ++i) {
+        if (i->frame >= note.frame &&
+            i->frame < note.frame + note.duration) {
+            pitchValues.push_back((*i).value);
+        }
     }
+        
+    if (pitchValues.empty()) return false;
+
     sort(pitchValues.begin(), pitchValues.end());
     size_t size = pitchValues.size();
     double median;
@@ -1385,6 +1422,8 @@
     }
     
     note.value = median;
+
+    return true;
 }
 
 void 
--- a/layer/FlexiNoteLayer.h	Thu Mar 27 15:59:46 2014 +0000
+++ b/layer/FlexiNoteLayer.h	Thu Mar 27 16:30:26 2014 +0000
@@ -80,6 +80,7 @@
 
     void splitNotesAt(View *v, int frame);
     void snapSelectedNotesToPitchTrack(View *v, Selection s);
+    void mergeNotes(View *v, Selection s);
 
     virtual const Model *getModel() const { return m_model; }
     void setModel(FlexiNoteModel *model);
@@ -173,7 +174,7 @@
     bool getNoteToEdit(View *v, int x, int y, FlexiNoteModel::Point &) const;
     void getRelativeMousePosition(View *v, FlexiNoteModel::Point &note, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const;
     SparseTimeValueModel *getAssociatedPitchModel(View *v) const;
-    void updateNoteValue(View *v, FlexiNoteModel::Point &note) const;
+    bool updateNoteValue(View *v, FlexiNoteModel::Point &note) const;
 
     FlexiNoteModel *m_model;
     bool m_editing;