X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fmidi-chunk.cc;h=aed9e2b7ddf7bc6fd2ceec5e1cd5a1c8bc92c8cd;hb=90e4d7057f3857da049dfda3d130017d4719bd6b;hp=804a6e1a0729428bac4ea4bdd499862d4adcc034;hpb=f93e4199873c91ae32f0e84a610d14853dc379df;p=lilypond.git diff --git a/lily/midi-chunk.cc b/lily/midi-chunk.cc index 804a6e1a07..aed9e2b7dd 100644 --- a/lily/midi-chunk.cc +++ b/lily/midi-chunk.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 2007--2011 Han-Wen Nienhuys + Copyright (C) 2007--2015 Han-Wen Nienhuys 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::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 @@ -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;