2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "beaming-pattern.hh"
25 Represents a stem belonging to a beam. Sometimes (for example, if the stem
26 belongs to a rest and stemlets aren't used) the stem will be invisible.
28 The rhythmic_importance_ of an element tells us the significance of the
29 moment at which this element occurs. For example, an element that occurs at
30 a beat is more significant than one that doesn't. Smaller number are
31 more important. The rhythmic_importance_ is decided and filled in by
32 Beaming_pattern. A rhythmic_importance_ smaller than zero has extra
33 significance: it represents the start of a beat and therefore beams may
34 need to be subdivided.
36 Beam_rhythmic_element::Beam_rhythmic_element ()
39 rhythmic_importance_ = 0;
40 beam_count_drul_[LEFT] = 0;
41 beam_count_drul_[RIGHT] = 0;
43 factor_ = Rational (1);
44 tuplet_start_ = false;
47 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv,
48 Rational factor, bool tuplet_start)
51 rhythmic_importance_ = 0;
52 beam_count_drul_[LEFT] = i;
53 beam_count_drul_[RIGHT] = i;
56 tuplet_start_ = tuplet_start;
60 Beam_rhythmic_element::de_grace ()
62 if (start_moment_.grace_part_)
64 start_moment_.main_part_ = start_moment_.grace_part_;
65 start_moment_.grace_part_ = 0;
70 Beam_rhythmic_element::count (Direction d) const
72 return beam_count_drul_[d];
76 Finds the appropriate direction for the flags at the given index that
77 hang below the neighbouring flags. If
78 the stem has no more flags than either of its neighbours, this returns
82 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
84 // The extremal stems shouldn't be messed with, so it's appropriate to
85 // return CENTER here also.
86 if (i == 0 || i == infos_.size () - 1)
89 int count = infos_[i].count (LEFT); // Both directions should still be the same
90 int left_count = infos_[i - 1].count (RIGHT);
91 int right_count = infos_[i + 1].count (LEFT);
93 // If we are told to subdivide beams and we are next to a beat, point the
94 // beamlet away from the beat.
95 if (options.subdivide_beams_)
97 if (infos_[i].rhythmic_importance_ < 0)
99 else if (infos_[i + 1].rhythmic_importance_ < 0)
103 if (count <= left_count && count <= right_count)
105 else if (!options.strict_beat_beaming_)
107 // Try to avoid sticking-out flags as much as possible by pointing
108 // my flags at the neighbor with the most flags.
109 if (right_count > left_count)
111 else if (left_count > right_count)
115 // If all else fails, point the beamlet away from the important moment.
116 return (infos_[i].rhythmic_importance_ < infos_[i + 1].rhythmic_importance_)
121 Beaming_pattern::de_grace ()
123 for (vsize i = 0; i < infos_.size (); i++)
125 infos_[i].de_grace ();
130 Beaming_pattern::beamify (Beaming_options const &options)
132 if (infos_.size () <= 1)
135 unbeam_invisible_stems ();
137 if (infos_[0].start_moment_.grace_part_)
140 if (infos_[0].start_moment_ < Moment (0))
141 for (vsize i = 0; i < infos_.size (); i++)
142 infos_[i].start_moment_ += options.measure_length_;
144 find_rhythmic_importance (options);
146 vector <Direction> flag_directions;
147 // Get the initial flag directions
148 for (vsize i = 0; i < infos_.size (); i++)
149 flag_directions.push_back (flag_direction (options, i));
151 // Correct flag directions for subdivision
152 for (vsize i = 1; i < infos_.size () - 1; i++)
154 if ((flag_directions[i] == CENTER) && (flag_directions[i - 1] == LEFT))
155 flag_directions[i] = RIGHT;
156 if ((flag_directions[i] == CENTER) && (flag_directions[i + 1] == RIGHT))
157 flag_directions[i] = LEFT;
160 // Set the count on each side of the stem
161 // We need to run this code twice to make both the
162 // left and the right counts work properly
163 for (int i = 0; i < 2; i++)
164 for (vsize i = 1; i < infos_.size () - 1; i++)
166 Direction non_flag_dir = -flag_directions[i];
170 (infos_[i + 1].rhythmic_importance_ < 0 &&
171 options.subdivide_beams_)
172 // we're left of a subdivision
173 ? (i != infos_.size () - 2)
174 // respect the beam count for shortened beams ...
175 ? max (beam_count_for_rhythmic_position (i + 1),
176 beam_count_for_length (remaining_length (i + 1)))
177 // ... except if there's only one trailing stem
178 : beam_count_for_rhythmic_position (i + 1)
180 // we're at any other stem
181 : min (min (infos_[i].count (non_flag_dir),
182 infos_[i + non_flag_dir].count (-non_flag_dir)),
183 infos_[i - non_flag_dir].count (non_flag_dir));
185 // Ensure at least one beam is left, even for groups longer than 1/8
186 count = max (count, 1);
188 infos_[i].beam_count_drul_[non_flag_dir] = count;
194 Set the tuplet start moment as necessary
197 update_tuplet (Moment start_moment, Rational factor, Moment *tuplet_start_moment)
199 int tuplet_number = (int) factor.den ();
200 if ((tuplet_number > 1) && (tuplet_start_moment->num () < 0))
201 *tuplet_start_moment = start_moment;
202 else if (tuplet_number == 1)
203 *tuplet_start_moment = Moment (-1, 1);
207 Get the group start position, the next group starting position, and the
208 next beat starting position, given start_moment, base_moment,
212 find_location (SCM grouping, Moment base_moment, Moment start_moment,
213 Rational factor, Moment *group_pos, Moment *next_group_pos,
214 Moment *next_beat_pos)
216 *group_pos = Moment (0);
217 *next_group_pos = Moment (0);
218 *next_beat_pos = base_moment;
220 while (*next_beat_pos <= start_moment)
221 *next_beat_pos += base_moment;
223 while (*next_group_pos < *next_beat_pos)
225 I64 group_count = 1; //default -- 1 base moments in a beam
226 if (scm_is_pair (grouping))
228 group_count = scm_to_int (scm_car (grouping));
229 grouping = scm_cdr (grouping);
232 // If we have a tuplet, the count should be determined from
233 // the maximum tuplet size for beamed tuplets.
234 U64 tuplet_number = factor.den ();
235 if (tuplet_number > 1U)
237 // We use 1/8 as the base moment for the tuplet because it's
238 // the largest beamed value. If the tuplet is shorter, it's
239 // OK, the code still works
240 I64 test_count = ( Moment (Rational (1, 8) / factor) / base_moment).num ();
241 if (test_count > group_count) group_count = test_count;
243 *group_pos = *next_group_pos;
244 *next_group_pos = *group_pos + Rational(group_count) * base_moment;
249 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
251 Moment group_pos (0); // 0 is the start of the first group
252 Moment next_group_pos (0);
253 Moment next_beat_pos (options.base_moment_);
254 Moment tuplet_start_moment (-1, 1);
255 I64 tuplet_number = 1;
257 SCM grouping = options.grouping_;
260 // Find where we are in the beat structure of the measure
262 find_location (grouping, options.base_moment_, infos_[i].start_moment_,
263 infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
265 // Mark the importance of stems that start at a beat or a beat group.
266 while (i < infos_.size ())
268 if ((next_beat_pos > next_group_pos)
269 || (infos_[i].start_moment_ > next_beat_pos))
270 // Find the new group ending point
271 find_location (grouping, options.base_moment_, infos_[i].start_moment_,
272 infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
273 // Mark the start of this beat group
274 if (infos_[i].start_moment_ == group_pos)
275 infos_[i].rhythmic_importance_ = -2;
276 // Work through the end of the beat group or the end of the beam
277 while (i < infos_.size () && infos_[i].start_moment_ < next_group_pos)
279 // Set the tuplet start as necessary
280 update_tuplet (infos_[i].start_moment_, infos_[i].factor_, &tuplet_start_moment);
281 Moment dt = infos_[i].start_moment_ - group_pos;
282 Rational tuplet = infos_[i].factor_;
283 Moment tuplet_moment (tuplet);
284 Moment tuplet_dt = infos_[i].start_moment_ - tuplet_start_moment;
285 tuplet_number = tuplet.den ();
286 // set the beat end and increment the next beat
287 if (infos_[i].start_moment_ == next_beat_pos)
289 infos_[i].rhythmic_importance_ = -1;
290 next_beat_pos += options.base_moment_;
292 // The rhythmic importance of a stem between beats depends on its fraction
293 // of a beat: those stems with a lower denominator are deemed more
294 // important. For tuplets, we need to make sure that we use
295 // the fraction of the tuplet, instead of the fraction of
297 Moment ratio = (tuplet_number == 1)
298 ? dt / options.base_moment_
299 : tuplet_dt / Moment (1, 8) / tuplet_moment;
300 if (infos_[i].rhythmic_importance_ >= 0)
301 infos_[i].rhythmic_importance_ = (int) ratio.den ();
306 if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
308 if (tuplet_number == 1)
309 infos_[i].rhythmic_importance_ = -1;
310 next_beat_pos += options.base_moment_;
311 if (infos_[i].start_moment_ == next_group_pos)
312 infos_[i].rhythmic_importance_ = -2;
318 Invisible stems should be treated as though they have the same number of
319 beams as their least-beamed neighbour. Here we go through the stems and
320 modify the invisible stems to satisfy this requirement.
323 Beaming_pattern::unbeam_invisible_stems ()
325 for (vsize i = 1; i < infos_.size (); i++)
326 if (infos_[i].invisible_)
328 int b = min (infos_[i].count (LEFT), infos_[i - 1].count (LEFT));
329 infos_[i].beam_count_drul_[LEFT] = b;
330 infos_[i].beam_count_drul_[RIGHT] = b;
333 if (infos_.size () > 1)
334 for (vsize i = infos_.size () - 1; i--;)
335 if (infos_[i].invisible_)
337 int b = min (infos_[i].count (LEFT), infos_[i + 1].count (LEFT));
338 infos_[i].beam_count_drul_[LEFT] = b;
339 infos_[i].beam_count_drul_[RIGHT] = b;
344 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor, bool tuplet_start)
346 infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor, tuplet_start));
349 Beaming_pattern::Beaming_pattern ()
354 Beaming_pattern::beamlet_count (int i, Direction d) const
356 return infos_.at (i).beam_count_drul_[d];
360 Beaming_pattern::start_moment (int i) const
362 return infos_.at (i).start_moment_;
366 Beaming_pattern::end_moment (int i) const
368 Duration dur (2 + max (beamlet_count (i, LEFT),
369 beamlet_count (i, RIGHT)),
372 return infos_.at (i).start_moment_
373 + infos_.at (i).factor_ * dur.get_length ();
377 Beaming_pattern::remaining_length (int i) const
379 return end_moment (infos_.size () - 1) - infos_[i].start_moment_;
383 Beaming_pattern::beam_count_for_rhythmic_position (int idx) const
385 // Calculate number of beams representing the rhythmic position of given stem
386 return intlog2(infos_[idx].start_moment_.main_part_.den()) - 2;
390 Beaming_pattern::beam_count_for_length (Moment len) const
392 return intlog2(len.main_part_.den()) - 2 - intlog2(len.main_part_.num());
396 Beaming_pattern::invisibility (int i) const
398 return infos_.at (i).invisible_;
402 Beaming_pattern::factor (int i) const
404 return infos_.at (i).factor_;
408 Beaming_pattern::tuplet_start (int i) const
410 return infos_.at (i).tuplet_start_;
414 Split a beaming pattern at index i and return a new
415 Beaming_pattern containing the removed elements
418 Beaming_pattern::split_pattern (int i)
420 Beaming_pattern *new_pattern = 0;
423 new_pattern = new Beaming_pattern ();
424 for (vsize j = i + 1; j < infos_.size (); j++)
426 count = max (beamlet_count (j, LEFT), beamlet_count (j, RIGHT));
427 new_pattern->add_stem (start_moment (j),
433 for (vsize j = i + 1; j < infos_.size ();)
435 return (new_pattern);
439 Beaming_options::from_context (Context *context)
441 grouping_ = context->get_property ("beatStructure");
442 subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
443 strict_beat_beaming_ = to_boolean (context->get_property ("strictBeatBeaming"));
444 base_moment_ = robust_scm2moment (context->get_property ("baseMoment"),
446 measure_length_ = robust_scm2moment (context->get_property ("measureLength"),
450 Beaming_options::Beaming_options ()
453 subdivide_beams_ = false;
454 strict_beat_beaming_ = false;