]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/midi-chunk.cc
Release: bump Welcome versions.
[lilypond.git] / lily / midi-chunk.cc
index 9e5a828a602908badd83f5ef0ec8bfb73fa399e7..aed9e2b7ddf7bc6fd2ceec5e1cd5a1c8bc92c8cd 100644 (file)
@@ -1,7 +1,7 @@
 /*
   This file is part of LilyPond, the GNU music typesetter.
 
-  Copyright (C) 2007--2012 Han-Wen Nienhuys <hanwen@lilypond.org>
+  Copyright (C) 2007--2015 Han-Wen Nienhuys <hanwen@lilypond.org>
 
 
   LilyPond is free software: you can redistribute it and/or modify
@@ -74,7 +74,48 @@ Midi_track::add (int delta_ticks, Midi_item *midi)
   assert (delta_ticks >= 0);
 
   Midi_event *e = new Midi_event (delta_ticks, midi);
-  events_.push_back (e);
+
+  // Insertion position for the new event in the track.
+  vector<Midi_event *>::iterator position (events_.end ());
+  if (delta_ticks == 0
+      && (! dynamic_cast<Midi_note *> (midi)
+          || dynamic_cast<Midi_note_off *> (midi)))
+    {
+      // If the new event occurs at the same time as the most recently added
+      // one, and the event does not represent the start of a note, insert the
+      // new event before all notes (if any) already starting at this time.
+      // This is to force notes to be started only after all other events
+      // (such as changes in instruments) which occur at the same time have
+      // taken effect.
+      while (position != events_.begin ())
+        {
+          vector<Midi_event *>::iterator previous (position - 1);
+          if (! dynamic_cast<Midi_note *> ((*previous)->midi_)
+              || dynamic_cast<Midi_note_off *> ((*previous)->midi_))
+            {
+              // Found an event that does not represent the start of a note.
+              // Exit the loop to insert the new event in the track after this
+              // event.
+              break;
+            }
+          else if ((*previous)->delta_ticks_ != 0)
+            {
+              // Found the start of a new note with delta_ticks_ != 0.  Prepare
+              // to insert the new event before this event, swapping the
+              // delta_ticks_ fields of the events to keep the sequence of
+              // deltas consistent.
+              e->delta_ticks_ = (*previous)->delta_ticks_;
+              (*previous)->delta_ticks_ = 0;
+              position = previous;
+              break;
+            }
+          // Otherwise, the event in the track is the start of a note occurring
+          // at the same time as the new event: continue searching for the
+          // insertion position.
+          position = previous;
+        }
+    }
+  events_.insert (position, e);
 }
 
 string
@@ -140,7 +181,7 @@ Midi_chunk::~Midi_chunk ()
 }
 
 void
-Midi_chunk::set (string header_string, string data_string, string footer_string)
+Midi_chunk::set (const string &header_string, const string &data_string, const string &footer_string)
 {
   data_string_ = data_string;
   footer_string_ = footer_string;