X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fmidi-chunk.cc;h=aed9e2b7ddf7bc6fd2ceec5e1cd5a1c8bc92c8cd;hb=5d84bfad4626892bcffd05adcced53c8a2329047;hp=0aa11eb5497bc388f83b7e323217d46ab9705cbb;hpb=f114e3c33f9c37c39c7a3fedf66ca5a074785118;p=lilypond.git diff --git a/lily/midi-chunk.cc b/lily/midi-chunk.cc index 0aa11eb549..aed9e2b7dd 100644 --- a/lily/midi-chunk.cc +++ b/lily/midi-chunk.cc @@ -1,8 +1,8 @@ /* 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 it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ #include "string-convert.hh" Midi_track::Midi_track (int number, bool port) - : number_ (number) + : number_ (number) { // 4D 54 72 6B MTrk // 00 00 00 3B chunk length (59) @@ -42,14 +42,14 @@ Midi_track::Midi_track (int number, bool port) // mi = 1: minor key char const *data_str0 = "" - // "00" "ff58" "0404" "0218" "08" - // "00" "ff51" "0307" "a120" - // why a key at all, in midi? - // key: C - // "00" "ff59" "02" "00" "00" - // key: F (scsii-menuetto) - // "00" "ff59" "02" "ff" "00" - ; + // "00" "ff58" "0404" "0218" "08" + // "00" "ff51" "0307" "a120" + // why a key at all, in midi? + // key: C + // "00" "ff59" "02" "00" "00" + // key: F (scsii-menuetto) + // "00" "ff59" "02" "ff" "00" + ; string data_string; // only for format 0 (currently using format 1)? @@ -58,7 +58,7 @@ Midi_track::Midi_track (int number, bool port) if (port) { string port = "00" "ff" "21" "01" - + String_convert::int2hex (number_, 2, '0'); + + String_convert::int2hex (number_, 2, '0'); data_string += String_convert::hex2bin (port); } @@ -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 @@ -82,18 +123,17 @@ Midi_track::data_string () const { string str = Midi_chunk::data_string (); - for (vector::const_iterator i (events_.begin ()); - i != events_.end (); i ++) + for (vector::const_iterator i (events_.begin ()); + i != events_.end (); i++) { str += (*i)->to_string (); } return str; } - Midi_track::~Midi_track () { - junk_pointers (events_); + junk_pointers (events_); } /**************************************************************** @@ -114,7 +154,7 @@ Midi_event::to_string () const } /**************************************************************** header -*/ +*/ Midi_header::Midi_header (int format, int tracks, int clocks_per_4) { @@ -132,17 +172,16 @@ Midi_header::Midi_header (int format, int tracks, int clocks_per_4) set ("MThd", str, ""); } - /**************************************************************** chunk */ 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; @@ -161,7 +200,7 @@ Midi_chunk::to_string () const string str = header_string_; string dat = data_string (); string length_string = String_convert::int2hex (dat.length () - + footer_string_.length (), 8, '0'); + + footer_string_.length (), 8, '0'); length_string = String_convert::hex2bin (length_string); str += length_string;