From: Carl Date: Wed, 1 Feb 2012 04:56:19 +0000 (-0700) Subject: Fix tuplet subdivision (issue 2243) X-Git-Tag: release/2.15.30-1~40 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=206f8bfb286a1d67af997ad368ae0326505b95ad;p=lilypond.git Fix tuplet subdivision (issue 2243) 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. --- diff --git a/input/regression/tuplet-subdivision.ly b/input/regression/tuplet-subdivision.ly new file mode 100644 index 0000000000..08b164e9f0 --- /dev/null +++ b/input/regression/tuplet-subdivision.ly @@ -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 } + } +} diff --git a/lily/auto-beam-engraver.cc b/lily/auto-beam-engraver.cc index a7cc3cf257..41c96eae76 100644 --- a/lily/auto-beam-engraver.cc +++ b/lily/auto-beam-engraver.cc @@ -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); diff --git a/lily/beam-engraver.cc b/lily/beam-engraver.cc index 455239d5ed..a89435de68 100644 --- a/lily/beam-engraver.cc +++ b/lily/beam-engraver.cc @@ -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); } diff --git a/lily/beaming-pattern.cc b/lily/beaming-pattern.cc index cc569c7c73..b6b9060dda 100644 --- a/lily/beaming-pattern.cc +++ b/lily/beaming-pattern.cc @@ -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 (); diff --git a/lily/include/beaming-pattern.hh b/lily/include/beaming-pattern.hh index 704c8f070c..8b9318da5d 100644 --- a/lily/include/beaming-pattern.hh +++ b/lily/include/beaming-pattern.hh @@ -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); diff --git a/lily/stem-engraver.cc b/lily/stem-engraver.cc index cb9e6b535b..b2720731d3 100644 --- a/lily/stem-engraver.cc +++ b/lily/stem-engraver.cc @@ -41,13 +41,15 @@ class Stem_engraver : public Engraver vector 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) diff --git a/lily/stem.cc b/lily/stem.cc index 8eaf2321ea..8c0e128487 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -1133,6 +1133,7 @@ ADD_INTERFACE (Stem, "stemlet-length " "thickness " "tremolo-flag " + "tuplet-start " ); /****************************************************************/ diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 107518d531..fba256f4bf 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -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.")