]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix tuplet subdivision (issue 2243)
authorCarl <c_sorensen@byu.edu>
Wed, 1 Feb 2012 04:56:19 +0000 (21:56 -0700)
committerCarl <c_sorensen@byu.edu>
Fri, 10 Feb 2012 02:04:22 +0000 (19:04 -0700)
Have stem-engraver add information about tuplet-start, so that it can be passed
into beaming-pattern.  Then we subdivide only when we're at *both* start of beat
and start of tuplet.

input/regression/tuplet-subdivision.ly [new file with mode: 0644]
lily/auto-beam-engraver.cc
lily/beam-engraver.cc
lily/beaming-pattern.cc
lily/include/beaming-pattern.hh
lily/stem-engraver.cc
lily/stem.cc
scm/define-grob-properties.scm

diff --git a/input/regression/tuplet-subdivision.ly b/input/regression/tuplet-subdivision.ly
new file mode 100644 (file)
index 0000000..08b164e
--- /dev/null
@@ -0,0 +1,17 @@
+\version "2.15.30"
+
+\header {
+
+  texinfo = "
+Subdivision works properly for tuplets
+  "
+}
+
+\relative c'' {
+  \set subdivideBeams = ##t
+  \set baseMoment = #(ly:make-moment 1 8)
+  \set beatStructure = #'(2 2 2 2)
+  \repeat unfold 8 {
+    \times 2/3 { c16 e d }
+  }
+}
index a7cc3cf257abfd69bd2ff8eab2d5342b5cae66a8..41c96eae76b84f2c5468526d93406ce2c7527663 100644 (file)
@@ -429,7 +429,8 @@ Auto_beam_engraver::acknowledge_stem (Grob_info info)
   grouping_->add_stem (now - beam_start_moment_ + beam_start_location_,
                        durlog - 2,
                        Stem::is_invisible (stem),
-                       stem_duration->factor ());
+                       stem_duration->factor (),
+                       (stem->get_property ("tuplet-start") == SCM_BOOL_T));
   stems_->push_back (stem);
   last_add_mom_ = now;
   extend_mom_ = max (extend_mom_, now) + get_event_length (ev, now);
index 455239d5ed247b587fd9fe46e467fa60f8604a32..a89435de6871a6ff391ac34075cea7e3c3f44527 100644 (file)
@@ -291,7 +291,8 @@ Beam_engraver::acknowledge_stem (Grob_info info)
   beam_info_->add_stem (stem_location,
                         max (durlog - 2, 0),
                         Stem::is_invisible (stem),
-                        stem_duration->factor ());
+                        stem_duration->factor (),
+                        (stem->get_property ("tuplet-start") == SCM_BOOL_T));
   Beam::add_stem (beam_, stem);
 }
 
index cc569c7c73b696aad614dd2d7344f182803e3dac..b6b9060ddaeb59a9e3a3ed30782920148cee9919 100644 (file)
@@ -40,10 +40,11 @@ Beam_rhythmic_element::Beam_rhythmic_element ()
   beam_count_drul_[RIGHT] = 0;
   invisible_ = false;
   factor_ = Rational (1);
-
+  tuplet_start_ = false;
 }
 
-Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv, Rational factor)
+Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv, 
+  Rational factor, bool tuplet_start)
 {
   start_moment_ = m;
   rhythmic_importance_ = 0;
@@ -51,6 +52,7 @@ Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv, Rationa
   beam_count_drul_[RIGHT] = i;
   invisible_ = inv;
   factor_ = factor;
+  tuplet_start_ = tuplet_start;
 }
 
 void
@@ -269,10 +271,15 @@ Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
           Moment tuplet_dt = infos_[i].start_moment_ - tuplet_start_moment;
           tuplet_number = tuplet.den ();
           // set the beat end (if not in a tuplet) and increment the next beat
-          if (tuplet_number == 1 && infos_[i].start_moment_ == next_beat_pos)
+          if (infos_[i].start_moment_ == next_beat_pos)
             {
-              infos_[i].rhythmic_importance_ = -1;
-              next_beat_pos += options.base_moment_;
+              if (tuplet_number == 1)
+                {
+                  infos_[i].rhythmic_importance_ = -1;
+                  next_beat_pos += options.base_moment_;
+                }
+              if (infos_[i].tuplet_start_)
+                infos_[i].rhythmic_importance_ = -1;
             }
           // The rhythmic importance of a stem between beats depends on its fraction
           // of a beat: those stems with a lower denominator are deemed more
@@ -326,9 +333,9 @@ Beaming_pattern::unbeam_invisible_stems ()
 }
 
 void
-Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor)
+Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor, bool tuplet_start)
 {
-  infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor));
+  infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor, tuplet_start));
 }
 
 Beaming_pattern::Beaming_pattern ()
@@ -369,6 +376,12 @@ Beaming_pattern::factor (int i) const
   return infos_.at (i).factor_;
 }
 
+bool
+Beaming_pattern::tuplet_start (int i) const
+{
+  return infos_.at (i).tuplet_start_;
+}
+
 /*
     Split a beaming pattern at index i and return a new
     Beaming_pattern containing the removed elements
@@ -386,7 +399,8 @@ Beaming_pattern::split_pattern (int i)
       new_pattern->add_stem (start_moment (j),
                              count,
                              invisibility (j),
-                             factor (j));
+                             factor (j),
+                             tuplet_start (j));
     }
   for (vsize j = i + 1; j < infos_.size ();)
     infos_.pop_back ();
index 704c8f070c71a0417eefd71d52903c452370772e..8b9318da5d1ed5e96778a160666752318e70e10a 100644 (file)
@@ -46,7 +46,9 @@ struct Beam_rhythmic_element
 
   Rational factor_;
 
-  Beam_rhythmic_element (Moment, int, bool, Rational);
+  bool tuplet_start_;
+
+  Beam_rhythmic_element (Moment, int, bool, Rational, bool);
   Beam_rhythmic_element ();
 
   int count (Direction d) const;
@@ -64,10 +66,11 @@ public:
 
   void beamify (Beaming_options const &);
   void de_grace ();
-  void add_stem (Moment d, int beams, bool invisible, Rational factor);
+  void add_stem (Moment d, int beams, bool invisible, Rational factor, bool tuplet_starrt);
   int beamlet_count (int idx, Direction d) const;
   bool invisibility (int idx) const;
   Rational factor (int idx) const;
+  bool tuplet_start (int idx) const;
   Moment start_moment (int idx) const;
   Moment end_moment (int idx) const;
   Beaming_pattern *split_pattern (int idx);
index cb9e6b535b180d8684e8d7d3a26b13e97437af0d..b2720731d34c0fcc3b5de007c6a0fb9cf04065cb 100644 (file)
@@ -41,13 +41,15 @@ class Stem_engraver : public Engraver
   vector <Grob *> maybe_flags_;
   Stream_event *rhythmic_ev_;
   Stream_event *tremolo_ev_;
+  bool tuplet_start_;
 
   TRANSLATOR_DECLARATIONS (Stem_engraver);
 
 protected:
-  void make_stem (Grob_info);
+  void make_stem (Grob_info, bool);
 
   DECLARE_TRANSLATOR_LISTENER (tremolo);
+  DECLARE_TRANSLATOR_LISTENER (tuplet_span);
   DECLARE_ACKNOWLEDGER (rhythmic_head);
   void stop_translation_timestep ();
   void finalize ();
@@ -60,14 +62,17 @@ Stem_engraver::Stem_engraver ()
   stem_ = 0;
   tremolo_ = 0;
   rhythmic_ev_ = 0;
+  tuplet_start_ = false;
 }
 
 void
-Stem_engraver::make_stem (Grob_info gi)
+Stem_engraver::make_stem (Grob_info gi, bool tuplet_start)
 {
   /* Announce the cause of the head as cause of the stem.  The
      stem needs a rhythmic structure to fit it into a beam.  */
   stem_ = make_item ("Stem", gi.grob ()->self_scm ());
+  if (tuplet_start)
+    stem_->set_property ("tuplet-start", SCM_BOOL_T);
   (void) make_item ("StemStub", gi.grob ()->self_scm ());
   if (tremolo_ev_)
     {
@@ -134,7 +139,8 @@ Stem_engraver::acknowledge_rhythmic_head (Grob_info gi)
     return;
 
   if (!stem_)
-    make_stem (gi);
+      make_stem (gi, tuplet_start_);
+      
 
   int ds = Stem::duration_log (stem_);
   int dc = d->duration_log ();
@@ -170,6 +176,8 @@ Stem_engraver::acknowledge_rhythmic_head (Grob_info gi)
       stem_->set_object ("flag", flag->self_scm ());
       maybe_flags_.push_back (flag);
     }
+  if (tuplet_start_) 
+    stem_->set_property ("tuplet-start", SCM_BOOL_T);
 }
 
 void
@@ -210,9 +218,24 @@ Stem_engraver::stop_translation_timestep ()
         }
       stem_ = 0;
     }
+  tuplet_start_ = false;
   tremolo_ev_ = 0;
 }
 
+IMPLEMENT_TRANSLATOR_LISTENER (Stem_engraver, tuplet_span);
+void
+Stem_engraver::listen_tuplet_span (Stream_event *ev)
+{
+  Direction dir = to_dir (ev->get_property ("span-direction"));
+  if (dir == START)
+    {
+      // set stem property if stem already exists
+      if (stem_)
+        stem_->set_property ("tuplet-start", SCM_BOOL_T);
+      tuplet_start_ = true;  // stash the value for use in later creation 
+    }
+}
+
 IMPLEMENT_TRANSLATOR_LISTENER (Stem_engraver, tremolo);
 void
 Stem_engraver::listen_tremolo (Stream_event *ev)
index 8eaf2321ea3ecdb669df157bf959cfa4ff706c11..8c0e128487b4f48027bb7f23e8810b19aa229c56 100644 (file)
@@ -1133,6 +1133,7 @@ ADD_INTERFACE (Stem,
                "stemlet-length "
                "thickness "
                "tremolo-flag "
+               "tuplet-start "
               );
 
 /****************************************************************/
index 107518d531c002e3859759f99f060a3913bbad69..fba256f4bff7fafb283ba5bb86aedc509fa4c09f 100644 (file)
@@ -1131,6 +1131,7 @@ results, use @code{LEFT} and @code{RIGHT}.")
      (ties ,ly:grob-array? "A grob array of @code{Tie} objects.")
      (tremolo-flag ,ly:grob? "The tremolo object on a stem.")
      (tuplet-number ,ly:grob? "The number for a bracket.")
+     (tuplet-start ,boolean? "Is stem at the start of a tuplet?")
      (tuplets ,ly:grob-array? "An array of smaller tuplet brackets.")
      (X-colliding-grobs ,ly:grob-array? "Grobs that can collide
 with a self-aligned grob on the X-axis.")