2 beaming-info.cc -- implement Beam_rhythmic_element, Beaming_pattern
4 A Beaming_pattern object takes a set of stems at given moments and calculates
5 the pattern of their beam. That is, it works out, for each stem, how many
6 beams should be connected to the right and left sides of that stem. In
7 calculating this, Beaming_pattern takes into account
8 - the rhythmic position of the stems
9 - the options that are defined in Beaming_options
11 source file of the GNU LilyPond music typesetter
13 (c) 1999--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
16 #include "beaming-pattern.hh"
20 Represents a stem belonging to a beam. Sometimes (for example, if the stem
21 belongs to a rest and stemlets aren't used) the stem will be invisible.
23 The rhythmic_importance_ of an element tells us the significance of the
24 moment at which this element occurs. For example, an element that occurs at
25 a beat is more significant than one that doesn't. Smaller number are
26 more important. The rhythmic_importance_ is decided and filled in by
27 Beaming_pattern. A rhythmic_importance_ smaller than zero has extra
28 significance: it represents the start of a beat and therefore beams may
29 need to be subdivided.
31 Beam_rhythmic_element::Beam_rhythmic_element ()
34 rhythmic_importance_ = 0;
35 beam_count_drul_[LEFT] = 0;
36 beam_count_drul_[RIGHT] = 0;
41 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv)
44 rhythmic_importance_ = 0;
45 beam_count_drul_[LEFT] = i;
46 beam_count_drul_[RIGHT] = i;
51 Beam_rhythmic_element::de_grace ()
53 if (start_moment_.grace_part_)
55 start_moment_.main_part_ = start_moment_.grace_part_;
56 start_moment_.grace_part_ = 0;
61 Beam_rhythmic_element::count (Direction d) const
63 return beam_count_drul_[d];
67 Finds the appropriate direction for the flags at the given index that
68 hang below the neighbouring flags. If
69 the stem has no more flags than either of its neighbours, this returns
73 Beaming_pattern::flag_direction (vsize i) const
75 // The extremal stems shouldn't be messed with, so it's appropriate to
76 // return CENTER here also.
77 if (i == 0 || i == infos_.size () - 1)
80 int count = infos_[i].count (LEFT); // Both directions should still be the same
81 int left_count = infos_[i-1].count (RIGHT);
82 int right_count = infos_[i+1].count (LEFT);
84 if (count <= left_count && count <= right_count)
87 // Try to avoid sticking-out flags as much as possible by pointing my flags
88 // at the neighbour with the most flags.
89 else if (right_count > left_count)
91 else if (left_count > right_count)
94 // If all else fails, point the beamlet away from the important moment.
95 return (infos_[i].rhythmic_importance_ <= infos_[i+1].rhythmic_importance_) ? RIGHT : LEFT;
99 Beaming_pattern::de_grace ()
101 for (vsize i = 0; i < infos_.size (); i ++)
103 infos_[i].de_grace ();
108 Beaming_pattern::beamify (Beaming_options const &options)
110 unbeam_invisible_stems ();
112 if (infos_.size () <= 1)
115 if (infos_[0].start_moment_.grace_part_)
118 if (infos_[0].start_moment_ < Moment (0))
119 for (vsize i = 0; i < infos_.size (); i++)
120 infos_[i].start_moment_ += options.measure_length_;
122 find_rhythmic_importance (options);
124 for (vsize i = 1; i < infos_.size () - 1; i++)
126 Direction non_flag_dir = other_dir (flag_direction (i));
129 int importance = (non_flag_dir == LEFT)
130 ? infos_[i].rhythmic_importance_ : infos_[i+1].rhythmic_importance_;
131 int count = (importance < 0)
132 ? 1 : min (infos_[i].count (non_flag_dir),
133 infos_[i+non_flag_dir].count (-non_flag_dir));
135 infos_[i].beam_count_drul_[non_flag_dir] = count;
141 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
143 Moment measure_pos (0);
144 SCM grouping = options.grouping_;
147 // Mark the importance of stems that start at a beat or a beat group.
148 while (i < infos_.size ())
150 // If a beat grouping is not specified, default to 2 beats per group.
152 if (scm_is_pair (grouping))
154 count = scm_to_int (scm_car (grouping));
155 grouping = scm_cdr (grouping);
158 // Mark the start of this beat group
159 if (infos_[i].start_moment_ == measure_pos)
160 infos_[i].rhythmic_importance_ = -2;
162 // Mark the start of each beat up to the end of this beat group.
163 for (int beat = 1; beat <= count; beat++)
165 Moment next_measure_pos = measure_pos + options.beat_length_;
167 while (i < infos_.size () && infos_[i].start_moment_ < next_measure_pos)
169 Moment dt = infos_[i].start_moment_ - measure_pos;
171 // The rhythmic importance of a stem between beats depends on its fraction
172 // of a beat: those stems with a lower denominator are deemed more
174 // FIXME: This is not the right way to do things for tuplets. For example,
175 // in an 8th-note triplet with a quarter-note beat, 1/3 of a beat should be
176 // more important than 1/2.
177 if (infos_[i].rhythmic_importance_ >= 0)
178 infos_[i].rhythmic_importance_ = (dt / options.beat_length_).den ();
183 measure_pos = next_measure_pos;
184 if (i < infos_.size () && infos_[i].start_moment_ == measure_pos)
185 infos_[i].rhythmic_importance_ = -1;
192 Invisible stems should be treated as though they have the same number of
193 beams as their least-beamed neighbour. Here we go through the stems and
194 modify the invisible stems to satisfy this requirement.
197 Beaming_pattern::unbeam_invisible_stems ()
199 for (vsize i = 1; i < infos_.size (); i++)
200 if (infos_[i].invisible_)
202 int b = min (infos_[i].count (LEFT), infos_[i-1].count (LEFT));
203 infos_[i].beam_count_drul_[LEFT] = b;
204 infos_[i].beam_count_drul_[RIGHT] = b;
207 for (vsize i = infos_.size (); i--;)
208 if (infos_[i].invisible_)
210 int b = min (infos_[i].count (LEFT), infos_[i+1].count (LEFT));
211 infos_[i].beam_count_drul_[LEFT] = b;
212 infos_[i].beam_count_drul_[RIGHT] = b;
218 Beaming_pattern::add_stem (Moment m, int b, bool invisible)
220 infos_.push_back (Beam_rhythmic_element (m, b, invisible));
223 Beaming_pattern::Beaming_pattern ()
228 Beaming_pattern::beamlet_count (int i, Direction d) const
230 return infos_.at (i).beam_count_drul_[d];
234 Beaming_options::from_context (Context *context)
236 grouping_ = context->get_property ("beatGrouping");
237 subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
238 beat_length_ = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4));
239 measure_length_ = robust_scm2moment (context->get_property ("measureLength"), Moment (1, 4));
242 Beaming_options::Beaming_options ()
245 subdivide_beams_ = false;