From: Karin Hoethker Date: Wed, 25 May 2011 11:38:29 +0000 (+0200) Subject: Remove duplicate ties for chords autosplit (1630) X-Git-Tag: release/2.14.2-1~48 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=63cbee29383943b9944eebdbadc537e7c28e2b4c;p=lilypond.git Remove duplicate ties for chords autosplit (1630) --- diff --git a/lily/completion-note-heads-engraver.cc b/lily/completion-note-heads-engraver.cc index 2534f6992b..3dfe32b0e3 100644 --- a/lily/completion-note-heads-engraver.cc +++ b/lily/completion-note-heads-engraver.cc @@ -27,7 +27,6 @@ using namespace std; #include "item.hh" #include "output-def.hh" #include "pitch.hh" -#include "pqueue.hh" #include "rhythmic-head.hh" #include "score-engraver.hh" #include "spanner.hh" @@ -41,19 +40,6 @@ using namespace std; /* TODO: make matching rest engraver. */ -struct Pending_tie -{ - Moment when_; - Stream_event* tie_event_; - Pending_tie () : tie_event_ (0) {} -}; - -static int -compare (Pending_tie const &a, Pending_tie const &b) -{ - return compare (a.when_, b.when_); -} - /* How does this work? @@ -78,9 +64,7 @@ class Completion_heads_engraver : public Engraver vector tie_note_candidates_; vector tie_note_candidate_events_; vector ties_; - PQueue pending_ties_; vector note_events_; - Stream_event *current_tie_event_; Moment note_end_mom_; bool is_first_; Rational left_to_do_; @@ -100,14 +84,12 @@ protected: void process_music (); void stop_translation_timestep (); DECLARE_TRANSLATOR_LISTENER (note); - DECLARE_TRANSLATOR_LISTENER (tie); }; void Completion_heads_engraver::initialize () { is_first_ = false; - current_tie_event_ = 0; } IMPLEMENT_TRANSLATOR_LISTENER (Completion_heads_engraver, note); @@ -124,14 +106,6 @@ Completion_heads_engraver::listen_note (Stream_event *ev) do_nothing_until_ = Rational (0, 0); } -IMPLEMENT_TRANSLATOR_LISTENER (Completion_heads_engraver, tie); -void -Completion_heads_engraver::listen_tie (Stream_event *ev) -{ - is_first_ = true; - current_tie_event_ = ev; -} - /* The duration _until_ the next barline. */ @@ -169,14 +143,6 @@ Completion_heads_engraver::process_music () { if (!is_first_ && !left_to_do_) return; - - if (current_tie_event_) - { - Pending_tie pending; - pending.when_ = note_end_mom_; - pending.tie_event_ = current_tie_event_; - pending_ties_.insert (pending); - } is_first_ = false; @@ -229,26 +195,21 @@ Completion_heads_engraver::process_music () event->set_property ("length", Moment (note_dur.get_length ()).smobbed_copy ()); event->set_property ("duration-log", scm_from_int (note_dur.duration_log ())); + /* + The Completion_heads_engraver splits an event into a group of consecutive events. + For each event in the group, the property "autosplit-end" denotes whether the current event + was truncated during splitting. Based on "autosplit-end", the Tie_engraver decides whether a + tie event should be processed. + */ + event->set_property ("autosplit-end", + ly_bool2scm (left_to_do_ - note_dur.get_length () > Rational (0))); + Item *note = make_note_head (event); if (need_clone) event->unprotect (); notes_.push_back (note); } - if (pending_ties_.size () - && pending_ties_.front().when_ == now_mom()) - { - for (vsize i = 0; i < tie_note_candidate_events_.size(); i++) - for (vsize j = 0; j < note_events_.size(); j++) - { - Pitch *p = unsmob_pitch (note_events_[j]->get_property ("pitch")); - Pitch *p_last - = unsmob_pitch (tie_note_candidate_events_[i]->get_property ("pitch")); - if (p && p_last && *p == *p_last) - make_tie (tie_note_candidates_[i], notes_[j]); - } - } - if (prev_notes_.size () == notes_.size ()) { for (vsize i = 0; i < notes_.size (); i++) @@ -288,11 +249,6 @@ void Completion_heads_engraver::start_translation_timestep () { Moment now = now_mom (); - while (pending_ties_.size() && pending_ties_.front().when_ < now) - { - pending_ties_.delmin(); - } - current_tie_event_ = 0; if (note_end_mom_.main_part_ <= now.main_part_) { tie_note_candidate_events_ = note_events_; diff --git a/lily/tie-engraver.cc b/lily/tie-engraver.cc index b13e68050c..d7fb39db74 100644 --- a/lily/tie-engraver.cc +++ b/lily/tie-engraver.cc @@ -82,6 +82,7 @@ protected: void process_music (); void typeset_tie (Grob *); void report_unterminated_tie (Head_event_tuple const &); + bool has_autosplit_end (Stream_event *event); public: TRANSLATOR_DECLARATIONS (Tie_engraver); }; @@ -116,6 +117,18 @@ void Tie_engraver::report_unterminated_tie (Head_event_tuple const &tie_start) tie_start.head_->warning (_("unterminated tie")); } +/* + Determines whether the end of an event was created by + a split in Completion_heads_engraver or by user input. +*/ +bool +Tie_engraver::has_autosplit_end (Stream_event *event) +{ + if (event) + return to_boolean (event->get_property ("autosplit-end")); + return false; +} + void Tie_engraver::process_music () { @@ -146,8 +159,12 @@ Tie_engraver::acknowledge_note_head (Grob_info i) if (!right_ev || !left_ev) continue; - if (ly_is_equal (right_ev->get_property ("pitch"), - left_ev->get_property ("pitch"))) + /* + Make a tie only if pitches are equal or if event end was not generated by + Completion_heads_engraver. + */ + if (ly_is_equal (right_ev->get_property ("pitch"), left_ev->get_property ("pitch")) + && (!Tie_engraver::has_autosplit_end (left_ev))) { Grob *p = new Spanner (heads_to_tie_[i].tie_definition_); Moment end = heads_to_tie_[i].end_moment_; @@ -170,10 +187,12 @@ Tie_engraver::acknowledge_note_head (Grob_info i) ties_.push_back (p); heads_to_tie_.erase (heads_to_tie_.begin () + i); - // Prevent all other tied notes ending at the same moment (assume - // implicitly the notes have also started at the same moment!) - // from triggering an "unterminated tie" warning. Needed e.g. for - // ~ g + /* + Prevent all other tied notes ending at the same moment (assume + implicitly the notes have also started at the same moment!) + from triggering an "unterminated tie" warning. Needed e.g. for + ~ g + */ for (vsize j = heads_to_tie_.size (); j--;) { if (heads_to_tie_[j].end_moment_ == end) @@ -233,6 +252,12 @@ Tie_engraver::stop_translation_timestep () vector new_heads_to_tie; + /* + Whether tie event has been processed and can be deleted or should + be kept for later portions of a split note. + */ + bool event_processed = false; + for (vsize i = 0; i < now_heads_.size (); i++) { Grob *head = now_heads_[i]; @@ -262,8 +287,11 @@ Tie_engraver::stop_translation_timestep () tie_event = ev; } - if (left_ev && (tie_event || tie_stream_event)) + if (left_ev && (tie_event || tie_stream_event) + && (!Tie_engraver::has_autosplit_end (left_ev))) { + event_processed = true; + Head_event_tuple event_tup; SCM start_definition @@ -301,7 +329,13 @@ Tie_engraver::stop_translation_timestep () for (vsize i = 0; i < new_heads_to_tie.size (); i++) heads_to_tie_.push_back (new_heads_to_tie[i]); - event_ = 0; + /* + Discard event only if it has been processed with at least one + appropriate note. + */ + if (event_processed) + event_ = 0; + now_heads_.clear (); } diff --git a/scm/define-music-properties.scm b/scm/define-music-properties.scm index 78a2dec6e1..201efa6528 100644 --- a/scm/define-music-properties.scm +++ b/scm/define-music-properties.scm @@ -41,6 +41,8 @@ this @code{\\lyricsto} section.") (with @code{+} sign).") (augmented-slash ,boolean? "This figure is for an augmented figured bass (back-slashed number).") + (autosplit-end ,boolean? "Duration of event was truncated by automatic +splitting in @code{Completion_heads_engraver}.") (bass ,boolean? "Set if this note is a bass note in a chord.") (beat-structure ,list? "A beatStructure to be used in autobeaming.")