X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fbeaming-pattern.cc;h=b6b9060ddaeb59a9e3a3ed30782920148cee9919;hb=f1d318170db686e9215c391a448975d5e88fad91;hp=916ec145af96d0e438fe33db217439bc2d68660c;hpb=a42aaa559b71ce5776795fa11a7e1df9110d85b7;p=lilypond.git diff --git a/lily/beaming-pattern.cc b/lily/beaming-pattern.cc index 916ec145af..b6b9060dda 100644 --- a/lily/beaming-pattern.cc +++ b/lily/beaming-pattern.cc @@ -1,7 +1,7 @@ /* This file is part of LilyPond, the GNU music typesetter. - Copyright (C) 1999--2011 Han-Wen Nienhuys + Copyright (C) 1999--2012 Han-Wen Nienhuys LilyPond is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -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 @@ -99,9 +101,18 @@ Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const if (count <= left_count && count <= right_count) return CENTER; + else if (!options.strict_beat_beaming_) + { + // Try to avoid sticking-out flags as much as possible by pointing + // my flags at the neighbor with the most flags. + if (right_count > left_count) + return RIGHT; + else if (left_count > right_count) + return LEFT; + } // If all else fails, point the beamlet away from the important moment. - return (infos_[i].rhythmic_importance_ <= infos_[i + 1].rhythmic_importance_) + return (infos_[i].rhythmic_importance_ < infos_[i + 1].rhythmic_importance_) ? RIGHT : LEFT; } @@ -165,6 +176,20 @@ Beaming_pattern::beamify (Beaming_options const &options) } } +/* + Set the tuplet start moment as necessary +*/ +void +update_tuplet (Moment start_moment, Rational factor, Moment *tuplet_start_moment) +{ + int tuplet_number = (int) factor.den (); + if ((tuplet_number > 1) && (tuplet_start_moment->num () < 0)) + *tuplet_start_moment = start_moment; + else if (tuplet_number == 1) + *tuplet_start_moment = Moment (-1, 1); +} + + /* Get the group start position, the next group starting position, and the next beat starting position, given start_moment, base_moment, @@ -184,26 +209,26 @@ find_location (SCM grouping, Moment base_moment, Moment start_moment, while (*next_group_pos < *next_beat_pos) { - int count = 1; //default -- 1 base moments in a beam + int group_count = 1; //default -- 1 base moments in a beam if (scm_is_pair (grouping)) { - count = scm_to_int (scm_car (grouping)); + group_count = scm_to_int (scm_car (grouping)); grouping = scm_cdr (grouping); } // If we have a tuplet, the count should be determined from // the maximum tuplet size for beamed tuplets. - int tuplet_count = factor.num (); - if (tuplet_count > 1) + int tuplet_number = factor.den (); + if (tuplet_number > 1) { // We use 1/8 as the base moment for the tuplet because it's // the largest beamed value. If the tuplet is shorter, it's // OK, the code still works - int test_count = (tuplet_count * Moment (Rational (1, 8)) / base_moment).num (); - if (test_count > count) count = test_count; + int test_count = ( Moment (Rational (1, 8) / factor ) / base_moment).num (); + if (test_count > group_count) group_count = test_count; } *group_pos = *next_group_pos; - *next_group_pos = *group_pos + count * base_moment; + *next_group_pos = *group_pos + group_count * base_moment; } } @@ -213,7 +238,8 @@ Beaming_pattern::find_rhythmic_importance (Beaming_options const &options) Moment group_pos (0); // 0 is the start of the first group Moment next_group_pos (0); Moment next_beat_pos (options.base_moment_); - int tuplet_count = 1; + Moment tuplet_start_moment (-1, 1); + int tuplet_number = 1; SCM grouping = options.grouping_; vsize i = 0; @@ -226,7 +252,6 @@ Beaming_pattern::find_rhythmic_importance (Beaming_options const &options) // Mark the importance of stems that start at a beat or a beat group. while (i < infos_.size ()) { - tuplet_count = infos_[i].factor_.den (); if ((next_beat_pos > next_group_pos) || (infos_[i].start_moment_ > next_beat_pos)) // Find the new group ending point @@ -238,34 +263,45 @@ Beaming_pattern::find_rhythmic_importance (Beaming_options const &options) // Work through the end of the beat group or the end of the beam while (i < infos_.size () && infos_[i].start_moment_ < next_group_pos) { + // Set the tuplet start as necessary + update_tuplet (infos_[i].start_moment_, infos_[i].factor_, &tuplet_start_moment); Moment dt = infos_[i].start_moment_ - group_pos; Rational tuplet = infos_[i].factor_; Moment tuplet_moment (tuplet); + 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_count == 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 // important. For tuplets, we need to make sure that we use // the fraction of the tuplet, instead of the fraction of // a beat. - Moment ratio = (dt / options.base_moment_ / tuplet_moment); + Moment ratio = (tuplet_number == 1) + ? dt / options.base_moment_ + : tuplet_dt / Moment (1, 8) / tuplet_moment; if (infos_[i].rhythmic_importance_ >= 0) infos_[i].rhythmic_importance_ = (int) ratio.den (); + i++; } if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos) { - if (tuplet_count == 1) + if (tuplet_number == 1) infos_[i].rhythmic_importance_ = -1; next_beat_pos += options.base_moment_; if (infos_[i].start_moment_ == next_group_pos) infos_[i].rhythmic_importance_ = -2; - i++; } } } @@ -297,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 () @@ -340,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 @@ -357,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 (); @@ -369,6 +412,7 @@ Beaming_options::from_context (Context *context) { grouping_ = context->get_property ("beatStructure"); subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams")); + strict_beat_beaming_ = to_boolean (context->get_property ("strictBeatBeaming")); base_moment_ = robust_scm2moment (context->get_property ("baseMoment"), Moment (1, 4)); measure_length_ = robust_scm2moment (context->get_property ("measureLength"), @@ -379,4 +423,5 @@ Beaming_options::Beaming_options () { grouping_ = SCM_EOL; subdivide_beams_ = false; + strict_beat_beaming_ = false; }