From: Heikki Tauriainen Date: Mon, 30 Jul 2012 08:14:55 +0000 (+0200) Subject: Issue 2672/1: Midi fixes X-Git-Tag: release/2.15.42-1~16 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=1c980a9906a7ea01b9f99487e75580f7232f2491;p=lilypond.git Issue 2672/1: Midi fixes 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. --- diff --git a/.mailmap b/.mailmap index a8ae3180ee..78d92e31a2 100644 --- a/.mailmap +++ b/.mailmap @@ -98,6 +98,7 @@ Han-Wen Nienhuys #? Heikki Junes Heikki Junes Heikki Junes +Heikki Tauriainen Hu Haipeng Ian Hulin James E. Bailey diff --git a/lily/midi-chunk.cc b/lily/midi-chunk.cc index 9e5a828a60..699ec7e898 100644 --- a/lily/midi-chunk.cc +++ b/lily/midi-chunk.cc @@ -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::iterator position (events_.end ()); + if (delta_ticks == 0 + && (! dynamic_cast (midi) + || dynamic_cast (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::iterator previous (position - 1); + if (! dynamic_cast ((*previous)->midi_) + || dynamic_cast ((*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