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"
19 Beam_rhythmic_element::Beam_rhythmic_element ()
22 beam_count_drul_[LEFT] = 0;
23 beam_count_drul_[RIGHT] = 0;
28 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv)
31 beam_count_drul_[LEFT] = i;
32 beam_count_drul_[RIGHT] = i;
38 Beam_rhythmic_element::de_grace ()
40 if (start_moment_.grace_part_)
42 start_moment_.main_part_ = start_moment_.grace_part_;
43 start_moment_.grace_part_ = 0;
48 count_factor_twos (int x)
51 while (x && x % 2 == 0)
61 Returns true if splitting at the given index will result in a gap
62 between an invisible stem and a visible stem whose number of beams
63 is larger than the number of beams of the invisible stem.
66 Beaming_pattern::is_next_to_invisible_stem (vsize i) const
71 // In fact, we don't need to check that the visible stem has more beams
72 // than the invisible stem. unbeam_invisible_stems() ensures that the
73 // visible stem has at least as many stems as the invisible stem, so
74 // we only need to check that they are not equal.
75 return infos_[i].invisible_ != infos_[i-1].invisible_
76 && infos_[i].beam_count_drul_[LEFT] != infos_[i-1].beam_count_drul_[RIGHT];
80 Finds the best point at which to subdivide a beam. In order of priority
81 (highest to lowest) this is
82 - before or after an invisible beam
83 - at the start of a beat group
84 - at the start of a beat
85 - whose position in its beat has the smallest denominator (that is,
86 a stem that starts halfway through a beat will be preferred over stems
87 that start 1/3 or 2/3s of the way through the beat).
89 - at the start of a beat group
90 - at the start of a beat
91 - whose position in its beat has the smallest denominator
93 If the split point occurs at the start of a beat group or at the start of a
94 beat, at_boundary will be set to true. Otherwise, it will be set to false.
97 Beaming_pattern::best_splitpoint_index (bool *at_boundary) const
99 bool require_invisible = false;
100 for (vsize i = 0; i < infos_.size (); i++)
101 require_invisible |= is_next_to_invisible_stem (i);
104 for (vsize i = 1; i < infos_.size (); i++)
106 if (infos_[i].group_start_ == infos_[i].start_moment_
107 && (!require_invisible || is_next_to_invisible_stem (i)))
111 for (vsize i = 1; i < infos_.size (); i++)
113 if (infos_[i].beat_start_ == infos_[i].start_moment_
114 && (!require_invisible || is_next_to_invisible_stem (i)))
118 *at_boundary = false;
120 int min_den = INT_MAX;
123 for (vsize i = 1; i < infos_.size (); i++)
125 Moment dt = infos_[i].start_moment_ - infos_[i].beat_start_;
128 This is a kludge, for the most common case of 16th, 32nds
129 etc. What should really happen is that \times x/y should
130 locally introduce a voice-specific beat duration. (or
131 perhaps: a list of beat durations for nested tuplets.)
135 dt /= infos_[i].beat_length_;
137 if (dt.den () < min_den
138 && (!require_invisible || is_next_to_invisible_stem (i)))
149 Beaming_pattern::beam_extend_count (Direction d) const
151 if (infos_.size () == 1)
152 return infos_[0].beam_count_drul_[d];
154 Beam_rhythmic_element thisbeam = boundary (infos_, d, 0);
155 Beam_rhythmic_element next = boundary (infos_, d, 1);
157 return min (thisbeam.beam_count_drul_[-d], next.beam_count_drul_[d]);
161 Beaming_pattern::de_grace ()
163 for (vsize i = 0; i < infos_.size (); i ++)
165 infos_[i].de_grace ();
170 Beaming_pattern::beamify (Beaming_options const &options)
172 unbeam_invisible_stems ();
174 if (infos_.size () <= 1)
177 if (infos_[0].start_moment_.grace_part_)
180 if (infos_[0].start_moment_ < Moment (0))
181 for (vsize i = 0; i < infos_.size (); i++)
182 infos_[i].start_moment_ += options.measure_length_;
184 Moment measure_pos (0);
186 vector<Moment> group_starts;
187 vector<Moment> beat_starts;
189 // Find the starting moments of the beats and the groups.
190 SCM grouping = options.grouping_;
191 while (measure_pos <= infos_.back ().start_moment_)
194 if (scm_is_pair (grouping))
196 count = scm_to_int (scm_car (grouping));
197 grouping = scm_cdr (grouping);
200 group_starts.push_back (measure_pos);
201 for (int i = 0; i < count; i++)
203 beat_starts.push_back (measure_pos + options.beat_length_ * i);
205 measure_pos += options.beat_length_ * count;
208 // Set the group_start_ and beam_start_ properties of each stem.
211 for (vsize i = 0; i < infos_.size (); i++)
213 while (j + 1 < group_starts.size ()
214 && group_starts[j+1] <= infos_[i].start_moment_)
217 if (j < group_starts.size ())
218 infos_[i].group_start_ = group_starts[j];
220 infos_[i].beat_length_ = options.beat_length_;
221 while (k + 1 < beat_starts.size ()
222 && beat_starts[k+1] <= infos_[i].start_moment_)
225 if (k < beat_starts.size ())
226 infos_[i].beat_start_ = beat_starts[k];
229 beamify (options.subdivide_beams_);
234 Determines beaming patterns by splitting the list of stems recursively.
236 Given a list of stems, we split it at the most 'natural' place (eg. at
237 the beginning of a beat) as determined by best_splitpoint_index. We
238 then beamify both subsets of beams. Finally, we determine the number of
239 beams between the subsets.
241 Note: if one of the subsets has only one element, we will not modify its
242 beams. This ensure that, for every stem, we will modify its beam count on at
246 Beaming_pattern::beamify (bool subdivide_beams)
248 if (infos_.size () <= 1)
251 Drul_array<Beaming_pattern> splits;
253 bool at_boundary = false;
254 int m = best_splitpoint_index (&at_boundary);
256 splits[LEFT].infos_ = vector<Beam_rhythmic_element> (infos_.begin (),
257 infos_.begin () + m);
258 splits[RIGHT].infos_ = vector<Beam_rhythmic_element> (infos_.begin () + m,
265 splits[d].beamify (subdivide_beams);
267 while (flip (&d) != LEFT);
269 int middle_beams = (at_boundary && subdivide_beams)
271 : min (splits[RIGHT].beam_extend_count (LEFT),
272 splits[LEFT].beam_extend_count (RIGHT));
276 if (splits[d].infos_.size () != 1)
277 boundary (splits[d].infos_, -d, 0).beam_count_drul_[-d] = middle_beams;
279 while (flip (&d) != LEFT);
281 infos_ = splits[LEFT].infos_;
282 infos_.insert (infos_.end (),
283 splits[RIGHT].infos_.begin (),
284 splits[RIGHT].infos_.end ());
289 Invisible stems should be treated as though they have the same number of
290 beams as their least-beamed neighbour. Here we go through the stems and
291 modify the invisible stems to satisfy this requirement.
294 Beaming_pattern::unbeam_invisible_stems ()
296 for (vsize i = 1; i < infos_.size (); i++)
297 if (infos_[i].invisible_)
299 int b = infos_[i-1].beam_count_drul_[LEFT];
300 infos_[i].beam_count_drul_[LEFT] = b;
301 infos_[i].beam_count_drul_[RIGHT] = b;
304 for (vsize i = infos_.size (); i--;)
305 if (infos_[i].invisible_)
307 int b = min (infos_[i].beam_count_drul_[LEFT], infos_[i+1].beam_count_drul_[LEFT]);
308 infos_[i].beam_count_drul_[LEFT] = b;
309 infos_[i].beam_count_drul_[RIGHT] = b;
315 Beaming_pattern::add_stem (Moment m, int b, bool invisible)
317 infos_.push_back (Beam_rhythmic_element (m, b, invisible));
320 Beaming_pattern::Beaming_pattern ()
325 Beaming_pattern::beamlet_count (int i, Direction d) const
327 return infos_.at (i).beam_count_drul_[d];
331 Beaming_options::from_context (Context *context)
333 grouping_ = context->get_property ("beatGrouping");
334 subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
335 beat_length_ = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4));
336 measure_length_ = robust_scm2moment (context->get_property ("measureLength"), Moment (1, 4));
339 Beaming_options::Beaming_options ()
342 subdivide_beams_ = false;