From 7adc0eb73854ea351f63feb22a218acf3a6ea865 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Thu, 11 Jan 2007 15:17:48 +0100 Subject: [PATCH] Fix #87. Excise moments from midi backend completely, and move duration to grace_part_ field in grace notes. This fixes MIDI syncing problems with grace notes. --- input/regression/midi-grace.ly | 34 ++++++++----------- lily/audio-column.cc | 7 ++++ lily/audio-item.cc | 24 ++++++++++---- lily/include/audio-column.hh | 2 +- lily/include/audio-item.hh | 4 +++ lily/include/midi-item.hh | 7 ++-- lily/include/midi-walker.hh | 10 +++--- lily/midi-item.cc | 25 ++++---------- lily/midi-walker.cc | 60 ++++++++++++++++++++-------------- lily/note-performer.cc | 9 ++++- lily/performance.cc | 22 ++----------- 11 files changed, 105 insertions(+), 99 deletions(-) diff --git a/input/regression/midi-grace.ly b/input/regression/midi-grace.ly index 213de79e37..5a58f3cbe8 100644 --- a/input/regression/midi-grace.ly +++ b/input/regression/midi-grace.ly @@ -1,22 +1,16 @@ -\version "2.10.0" -\header{ texidoc = "Tests MIDI output with grace notes. " } -\score { - \context Voice \relative c { - \new Voice = VoiceOne - \grace { - \override Stem #'stroke-style = #"grace" - c8 - \revert Stem #'stroke-style } - d4 d d d d - \grace { - \override Stem #'stroke-style = #"grace" - e16 f e f - \revert Stem #'stroke-style } - d4 d d d d - - } - \layout { } - \midi { } -} +\header { + texidoc = "Grace notes don't intrroduce syncing problems: the last note +off will appear at tick 768 (2 * 384)." + +} +\version "2.10.10" +\score { + \relative c' { + c4 + \grace { b8 } + d4 + } + \midi { } +} diff --git a/lily/audio-column.cc b/lily/audio-column.cc index 0bc1b6690f..d052c4e8cc 100644 --- a/lily/audio-column.cc +++ b/lily/audio-column.cc @@ -29,9 +29,16 @@ Audio_column::when () const return when_; } +int +Audio_column::ticks () const +{ + return int (moment_to_ticks (when_)); +} + void Audio_column::offset_when (Moment m) { when_ += m; } + diff --git a/lily/audio-item.cc b/lily/audio-item.cc index 9dd1322d28..41381458f6 100644 --- a/lily/audio-item.cc +++ b/lily/audio-item.cc @@ -75,11 +75,23 @@ Audio_span_dynamic::add_absolute (Audio_dynamic *d) dynamics_.push_back (d); } -static Real -moment2real (Moment m) +Moment +remap_grace_duration (Moment m) { - return m.main_part_.to_double () - + 0.1 * m.grace_part_.to_double (); + return Moment (m.main_part_ + Rational (9,40) * m.grace_part_, + Rational (0)); +} + +Real +moment_to_real (Moment m) +{ + return remap_grace_duration (m).main_part_.to_double (); +} + +int +moment_to_ticks (Moment m) +{ + return int (moment_to_real (m) * 384 * 4); } void @@ -113,14 +125,14 @@ Audio_span_dynamic::render () Moment start = dynamics_[0]->get_column ()->when (); - Real total_t = moment2real (dynamics_.back ()->get_column ()->when () - start); + Real total_t = moment_to_real (dynamics_.back ()->get_column ()->when () - start); for (vsize i = 1; i < dynamics_.size(); i ++) { Moment dt_moment = dynamics_[i]->get_column ()->when () - start; - Real dt = moment2real (dt_moment); + Real dt = moment_to_real (dt_moment); Real v = start_v + delta_v * (dt / total_t); diff --git a/lily/include/audio-column.hh b/lily/include/audio-column.hh index cefa44f5a8..0b10c8bd4d 100644 --- a/lily/include/audio-column.hh +++ b/lily/include/audio-column.hh @@ -26,7 +26,7 @@ public: vector audio_items_; Moment when_; - + int ticks () const ; protected: void offset_when (Moment m); friend class Score_performer; diff --git a/lily/include/audio-item.hh b/lily/include/audio-item.hh index 00fb2bce8d..c02eba58c1 100644 --- a/lily/include/audio-item.hh +++ b/lily/include/audio-item.hh @@ -122,5 +122,9 @@ public: int one_beat_; }; +int moment_to_ticks (Moment); +Real moment_to_real (Moment); +Moment remap_grace_duration (Moment); + #endif // AUDIO_ITEM_HH diff --git a/lily/include/midi-item.hh b/lily/include/midi-item.hh index 9dd942bffc..6d77f21afc 100644 --- a/lily/include/midi-item.hh +++ b/lily/include/midi-item.hh @@ -47,9 +47,9 @@ public: class Midi_event { public: - Midi_event (Moment delta_mom, Midi_item *midi); + Midi_event (int delta, Midi_item *midi); - Moment delta_mom_; + int delta_ticks_; Midi_item *midi_; string to_string () const; }; @@ -134,7 +134,6 @@ public: Midi_note (Audio_note *); DECLARE_CLASSNAME(Midi_note); - Moment get_length () const; int get_semitone_pitch () const; int get_fine_tuning () const; virtual string to_string () const; @@ -225,7 +224,7 @@ public: Midi_track (); ~Midi_track (); - void add (Moment delta_time_mom, Midi_item *midi); + void add (int, Midi_item *midi); virtual string data_string () const; }; diff --git a/lily/include/midi-walker.hh b/lily/include/midi-walker.hh index bc12bb9aa6..ee523e5faa 100644 --- a/lily/include/midi-walker.hh +++ b/lily/include/midi-walker.hh @@ -12,7 +12,7 @@ #include "lily-proto.hh" #include "moment.hh" -struct Midi_note_event : PQueue_ent +struct Midi_note_event : PQueue_ent { bool ignore_b_; Midi_note_event (); @@ -36,16 +36,16 @@ public: private: void do_start_note (Midi_note *note); - void do_stop_notes (Moment now_mom); - void output_event (Moment now_mom, Midi_item *l); + void do_stop_notes (int); + void output_event (int, Midi_item *l); int channel_; Midi_track *track_; Audio_staff *staff_; vsize index_; - vector *items_; + vector items_; PQueue stop_note_queue; - Moment last_mom_; + int last_tick_; }; #endif // MIDI_WALKER_HH diff --git a/lily/midi-item.cc b/lily/midi-item.cc index ebbb20aeec..ee05d4ed58 100644 --- a/lily/midi-item.cc +++ b/lily/midi-item.cc @@ -90,21 +90,16 @@ Midi_duration::to_string () const return string (""; } -Midi_event::Midi_event (Moment delta_mom, Midi_item *midi) +Midi_event::Midi_event (int delta_ticks, Midi_item *midi) { - delta_mom_ = delta_mom; + delta_ticks_ = delta_ticks; midi_ = midi; } string Midi_event::to_string () const { - assert (delta_mom_.grace_part_ == Rational (0)); - - Rational rat_dt = delta_mom_.main_part_ * Rational (384) * Rational (4); - int delta = rat_dt.to_int (); - - string delta_string = Midi_item::i2varint_string (delta); + string delta_string = Midi_item::i2varint_string (delta_ticks_); string midi_string = midi_->to_string (); assert (midi_string.length ()); return delta_string + midi_string; @@ -243,12 +238,6 @@ Midi_note::Midi_note (Audio_note *a) dynamic_byte_ = 0x7f; } -Moment -Midi_note::get_length () const -{ - Moment m = audio_->end_column_->when () - audio_->audio_column_->when (); - return m; -} int Midi_note::get_fine_tuning () const @@ -292,7 +281,7 @@ Midi_note::to_string () const str += ::to_string ((char) (0x00)); } - str += ::to_string ((char)status_byte); + str += ::to_string ((char) status_byte); str += ::to_string ((char) (get_semitone_pitch () + c0_pitch_)); str += ::to_string ((char)dynamic_byte_); @@ -454,11 +443,11 @@ Midi_track::Midi_track () } void -Midi_track::add (Moment delta_time_mom, Midi_item *midi) +Midi_track::add (int delta_ticks, Midi_item *midi) { - assert (delta_time_mom >= Moment (0)); + assert (delta_ticks >= 0); - Midi_event *e = new Midi_event (delta_time_mom, midi); + Midi_event *e = new Midi_event (delta_ticks, midi); events_.push_back (e); } diff --git a/lily/midi-walker.cc b/lily/midi-walker.cc index 3bdc426be0..aa491bc930 100644 --- a/lily/midi-walker.cc +++ b/lily/midi-walker.cc @@ -33,21 +33,27 @@ compare (Midi_note_event const &left, Midi_note_event const &right) return 0; } +bool +audio_item_less (Audio_item * const a, + Audio_item * const b) +{ + return a->get_column ()->when_ < b->get_column ()->when_; +} + Midi_walker::Midi_walker (Audio_staff *audio_staff, Midi_track *track, int channel) { channel_ = channel; track_ = track; index_ = 0; - items_ = &audio_staff->audio_items_; - - last_mom_ = 0; + items_ = audio_staff->audio_items_; + vector_sort (items_, audio_item_less); + last_tick_ = 0; } Midi_walker::~Midi_walker () { - // ugh - do_stop_notes (last_mom_ + Moment (Rational (10, 1))); + do_stop_notes (last_tick_ + 384); } /** @@ -56,8 +62,9 @@ Midi_walker::~Midi_walker () void Midi_walker::do_start_note (Midi_note *note) { - Audio_item *ptr = (*items_)[index_]; - Moment stop_mom = note->get_length () + ptr->audio_column_->when (); + Audio_item *ptr = items_[index_]; + int stop_ticks = int (moment_to_real (note->audio_->length_mom_) * Real (384 * 4)) + + ptr->audio_column_->ticks (); bool play_start = true; for (vsize i = 0; i < stop_note_queue.size (); i++) @@ -66,7 +73,7 @@ Midi_walker::do_start_note (Midi_note *note) if (stop_note_queue[i].val->get_semitone_pitch () == note->get_semitone_pitch ()) { - if (stop_note_queue[i].key < stop_mom) + if (stop_note_queue[i].key < stop_ticks) { /* let stopnote in queue be ignored, new stop note wins */ @@ -90,11 +97,11 @@ Midi_walker::do_start_note (Midi_note *note) { Midi_note_event e; e.val = new Midi_note_off (note); - e.key = stop_mom; + e.key = int (stop_ticks); stop_note_queue.insert (e); if (play_start) - output_event (ptr->audio_column_->when (), note); + output_event (ptr->audio_column_->ticks (), note); } } @@ -102,9 +109,9 @@ Midi_walker::do_start_note (Midi_note *note) Output note events for all notes which end before #max_mom# */ void -Midi_walker::do_stop_notes (Moment max_mom) +Midi_walker::do_stop_notes (int max_ticks) { - while (stop_note_queue.size () && stop_note_queue.front ().key <= max_mom) + while (stop_note_queue.size () && stop_note_queue.front ().key <= max_ticks) { Midi_note_event e = stop_note_queue.get (); if (e.ignore_b_) @@ -113,10 +120,10 @@ Midi_walker::do_stop_notes (Moment max_mom) continue; } - Moment stop_mom = e.key; + int stop_ticks = e.key; Midi_note *note = e.val; - output_event (stop_mom, note); + output_event (stop_ticks, note); } } @@ -124,26 +131,29 @@ Midi_walker::do_stop_notes (Moment max_mom) Advance the track to #now#, output the item, and adjust current "moment". */ void -Midi_walker::output_event (Moment now_mom, Midi_item *l) +Midi_walker::output_event (int now_ticks, Midi_item *l) { - Moment delta_t = now_mom - last_mom_; - last_mom_ = now_mom; + int delta_ticks = now_ticks - last_tick_; + last_tick_ = now_ticks; /* this is not correct, but at least it doesn't crash when you start with graces */ - if (delta_t < Moment (0)) - delta_t = Moment (0); + if (delta_ticks < 0) + { + programming_error ("Going back in MIDI time."); + delta_ticks = 0; + } - track_->add (delta_t, l); + track_->add (delta_ticks, l); } void Midi_walker::process () { - Audio_item *audio = (*items_)[index_]; - do_stop_notes (audio->audio_column_->when ()); + Audio_item *audio = items_[index_]; + do_stop_notes (audio->audio_column_->ticks ()); if (Midi_item *midi = Midi_item::get_midi (audio)) { @@ -153,18 +163,18 @@ Midi_walker::process () //midi->channel_ = track_->number_; if (Midi_note *note = dynamic_cast (midi)) { - if (note->get_length ().to_bool ()) + if (note->audio_->length_mom_.to_bool ()) do_start_note (note); } else - output_event (audio->audio_column_->when (), midi); + output_event (audio->audio_column_->ticks (), midi); } } bool Midi_walker::ok () const { - return index_ < items_->size (); + return index_ < items_.size (); } void diff --git a/lily/note-performer.cc b/lily/note-performer.cc index a1503f2b61..ff296311ff 100644 --- a/lily/note-performer.cc +++ b/lily/note-performer.cc @@ -65,7 +65,14 @@ Note_performer::process_music () tie_event = ev; } - Audio_note *p = new Audio_note (*pitp, get_event_length (n), + Moment len = get_event_length (n); + if (now_mom().grace_part_) + { + len.grace_part_ = len.main_part_; + len.main_part_ = Rational (0); + } + + Audio_note *p = new Audio_note (*pitp, len, tie_event, transposing.negated ()); Audio_element_info info (p, n); announce_element (info); diff --git a/lily/performance.cc b/lily/performance.cc index 78070a064a..2c02fc32f9 100644 --- a/lily/performance.cc +++ b/lily/performance.cc @@ -38,11 +38,9 @@ Performance::output (Midi_stream &midi_stream) const { int tracks_ = audio_staffs_.size (); - // ugh - int clocks_per_4 = 384; - - midi_stream << Midi_header (1, tracks_, clocks_per_4); - message (_ ("Track...") + " "); + midi_stream << Midi_header (1, tracks_, 384); + if (be_verbose_global) + progress_indication (_ ("Track...") + " "); int channel = 0; for (vsize i = 0; i < audio_staffs_.size (); i++) @@ -107,21 +105,7 @@ Performance::write_output (string out) const } -void -Performance::remap_grace_durations () -{ - for (vsize i = 0; i < audio_elements_.size (); i++) - { - if (Audio_column * col = dynamic_cast (audio_elements_[i])) - { - col->when_.main_part_ = col->when_.main_part_ + Rational (1,4) * col->when_.grace_part_; - col->when_.grace_part_ = Rational (0); - } - } -} - void Performance::process () { - remap_grace_durations (); } -- 2.39.5