]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 2672/1: Midi fixes
authorHeikki Tauriainen <g034737@welho.com>
Mon, 30 Jul 2012 08:14:55 +0000 (10:14 +0200)
committerDavid Kastrup <dak@gnu.org>
Mon, 30 Jul 2012 08:14:55 +0000 (10:14 +0200)
When other MIDI midi events (such as an instrument change) occur
simultaneously with note(s), they should be placed in the MIDI file
before the note-on events, otherwise there is no way to (reliably)
affect the first note in a score.

.mailmap
lily/midi-chunk.cc

index a8ae3180ee8e9461f7c339ce3e30abafa74cf437..78d92e31a2903b3d08f7571f28e43ffacea05a86 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -98,6 +98,7 @@ Han-Wen Nienhuys <uid67283> #?
 Heikki Junes <hjunes>
 Heikki Junes <hjunes@gmail.com>
 Heikki Junes <hjunes@hjunes-laptop.(none)>
+Heikki Tauriainen <g034737@welho.com>
 Hu Haipeng <hhpmusic@163.com>
 Ian Hulin <ian@hulin.org.uk>
 James E. Bailey <derhindemith@googlemail.com>
index 9e5a828a602908badd83f5ef0ec8bfb73fa399e7..699ec7e89876049d379858b5dd287118f4266271 100644 (file)
@@ -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