]> git.donarmstrong.com Git - lilypond.git/commitdiff
Remove duplicate ties for chords autosplit (1630)
authorKarin Hoethker <karin.hoethker@googlemail.com>
Wed, 25 May 2011 11:38:29 +0000 (13:38 +0200)
committerGraham Percival <graham@percival-music.ca>
Wed, 15 Jun 2011 12:38:40 +0000 (13:38 +0100)
lily/completion-note-heads-engraver.cc
lily/tie-engraver.cc
scm/define-music-properties.scm

index 2534f6992b126d9926d806a7b11513fdbc8b3aa2..3dfe32b0e3ec7531335476fe67fe53b9d75d1661 100644 (file)
@@ -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<Item*> tie_note_candidates_;
   vector<Stream_event*> tie_note_candidate_events_;
   vector<Grob*> ties_;
-  PQueue<Pending_tie> pending_ties_;
   vector<Stream_event*> 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_;
index b13e68050c97f0d2a162a27d6650837f0fd6b6cf..d7fb39db74649414ea38c6e6fa0970e534a180df 100644 (file)
@@ -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
-         // <c e g>~ 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
+           <c e g>~ 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<Head_event_tuple> 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 ();
 }
 
index 78a2dec6e1b71a89dd4624e9850180088e04b36b..201efa6528e8db2563c2e5e6e3ba6e0b001377c5 100644 (file)
@@ -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.")