X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fmidi-chunk.cc;h=48543b10dbd5a3da9e5b1a2684a591d83b2e7bc9;hb=59a6d1a06432fc0ca88c3023c646182f389ec1b5;hp=9e5a828a602908badd83f5ef0ec8bfb73fa399e7;hpb=d61cf3bbdb1c6670a127ba3baddf2f04d3e34fd3;p=lilypond.git diff --git a/lily/midi-chunk.cc b/lily/midi-chunk.cc index 9e5a828a60..48543b10db 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--2012 Han-Wen Nienhuys + Copyright (C) 2007--2015 Han-Wen Nienhuys LilyPond is free software: you can redistribute it and/or modify @@ -24,6 +24,9 @@ #include "std-string.hh" #include "string-convert.hh" +using std::string; +using std::vector; + Midi_track::Midi_track (int number, bool port) : number_ (number) { @@ -74,7 +77,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 +184,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;