2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2012 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"
24 Represents a stem belonging to a beam. Sometimes (for example, if the stem
25 belongs to a rest and stemlets aren't used) the stem will be invisible.
27 The rhythmic_importance_ of an element tells us the significance of the
28 moment at which this element occurs. For example, an element that occurs at
29 a beat is more significant than one that doesn't. Smaller number are
30 more important. The rhythmic_importance_ is decided and filled in by
31 Beaming_pattern. A rhythmic_importance_ smaller than zero has extra
32 significance: it represents the start of a beat and therefore beams may
33 need to be subdivided.
35 Beam_rhythmic_element::Beam_rhythmic_element ()
38 rhythmic_importance_ = 0;
39 beam_count_drul_[LEFT] = 0;
40 beam_count_drul_[RIGHT] = 0;
42 factor_ = Rational (1);
43 tuplet_start_ = false;
46 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv,
47 Rational factor, bool tuplet_start)
50 rhythmic_importance_ = 0;
51 beam_count_drul_[LEFT] = i;
52 beam_count_drul_[RIGHT] = i;
55 tuplet_start_ = tuplet_start;
59 Beam_rhythmic_element::de_grace ()
61 if (start_moment_.grace_part_)
63 start_moment_.main_part_ = start_moment_.grace_part_;
64 start_moment_.grace_part_ = 0;
69 Beam_rhythmic_element::count (Direction d) const
71 return beam_count_drul_[d];
75 Finds the appropriate direction for the flags at the given index that
76 hang below the neighbouring flags. If
77 the stem has no more flags than either of its neighbours, this returns
81 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
83 // The extremal stems shouldn't be messed with, so it's appropriate to
84 // return CENTER here also.
85 if (i == 0 || i == infos_.size () - 1)
88 int count = infos_[i].count (LEFT); // Both directions should still be the same
89 int left_count = infos_[i - 1].count (RIGHT);
90 int right_count = infos_[i + 1].count (LEFT);
92 // If we are told to subdivide beams and we are next to a beat, point the
93 // beamlet away from the beat.
94 if (options.subdivide_beams_)
96 if (infos_[i].rhythmic_importance_ < 0)
98 else if (infos_[i + 1].rhythmic_importance_ < 0)
102 if (count <= left_count && count <= right_count)
104 else if (!options.strict_beat_beaming_)
106 // Try to avoid sticking-out flags as much as possible by pointing
107 // my flags at the neighbor with the most flags.
108 if (right_count > left_count)
110 else if (left_count > right_count)
114 // If all else fails, point the beamlet away from the important moment.
115 return (infos_[i].rhythmic_importance_ < infos_[i + 1].rhythmic_importance_)
120 Beaming_pattern::de_grace ()
122 for (vsize i = 0; i < infos_.size (); i++)
124 infos_[i].de_grace ();
129 Beaming_pattern::beamify (Beaming_options const &options)
131 if (infos_.size () <= 1)
134 unbeam_invisible_stems ();
136 if (infos_[0].start_moment_.grace_part_)
139 if (infos_[0].start_moment_ < Moment (0))
140 for (vsize i = 0; i < infos_.size (); i++)
141 infos_[i].start_moment_ += options.measure_length_;
143 find_rhythmic_importance (options);
145 vector <Direction> flag_directions;
146 // Get the initial flag directions
147 for (vsize i = 0; i < infos_.size (); i++)
148 flag_directions.push_back (flag_direction (options, i));
150 // Correct flag directions for subdivision
151 for (vsize i = 1; i < infos_.size () - 1; i++)
153 if ((flag_directions[i] == CENTER) && (flag_directions[i - 1] == LEFT))
154 flag_directions[i] = RIGHT;
155 if ((flag_directions[i] == CENTER) && (flag_directions[i + 1] == RIGHT))
156 flag_directions[i] = LEFT;
159 // Set the count on each side of the stem
160 // We need to run this code twice to make both the
161 // left and the right counts work properly
162 for (int i = 0; i < 2; i++)
163 for (vsize i = 1; i < infos_.size () - 1; i++)
165 Direction non_flag_dir = other_dir (flag_directions[i]);
168 int importance = infos_[i + 1].rhythmic_importance_;
169 int count = (importance < 0 && options.subdivide_beams_)
170 ? 1 : min (min (infos_[i].count (non_flag_dir),
171 infos_[i + non_flag_dir].count (-non_flag_dir)),
172 infos_[i - non_flag_dir].count (non_flag_dir));
174 infos_[i].beam_count_drul_[non_flag_dir] = count;
180 Set the tuplet start moment as necessary
183 update_tuplet (Moment start_moment, Rational factor, Moment *tuplet_start_moment)
185 int tuplet_number = (int) factor.den ();
186 if ((tuplet_number > 1) && (tuplet_start_moment->num () < 0))
187 *tuplet_start_moment = start_moment;
188 else if (tuplet_number == 1)
189 *tuplet_start_moment = Moment (-1, 1);
194 Get the group start position, the next group starting position, and the
195 next beat starting position, given start_moment, base_moment,
199 find_location (SCM grouping, Moment base_moment, Moment start_moment,
200 Rational factor, Moment *group_pos, Moment *next_group_pos,
201 Moment *next_beat_pos)
203 *group_pos = Moment (0);
204 *next_group_pos = Moment (0);
205 *next_beat_pos = base_moment;
207 while (*next_beat_pos <= start_moment)
208 *next_beat_pos += base_moment;
210 while (*next_group_pos < *next_beat_pos)
212 int group_count = 1; //default -- 1 base moments in a beam
213 if (scm_is_pair (grouping))
215 group_count = scm_to_int (scm_car (grouping));
216 grouping = scm_cdr (grouping);
219 // If we have a tuplet, the count should be determined from
220 // the maximum tuplet size for beamed tuplets.
221 int tuplet_number = factor.den ();
222 if (tuplet_number > 1)
224 // We use 1/8 as the base moment for the tuplet because it's
225 // the largest beamed value. If the tuplet is shorter, it's
226 // OK, the code still works
227 int test_count = ( Moment (Rational (1, 8) / factor ) / base_moment).num ();
228 if (test_count > group_count) group_count = test_count;
230 *group_pos = *next_group_pos;
231 *next_group_pos = *group_pos + group_count * base_moment;
236 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
238 Moment group_pos (0); // 0 is the start of the first group
239 Moment next_group_pos (0);
240 Moment next_beat_pos (options.base_moment_);
241 Moment tuplet_start_moment (-1, 1);
242 int tuplet_number = 1;
244 SCM grouping = options.grouping_;
247 // Find where we are in the beat structure of the measure
249 find_location (grouping, options.base_moment_, infos_[i].start_moment_,
250 infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
252 // Mark the importance of stems that start at a beat or a beat group.
253 while (i < infos_.size ())
255 if ((next_beat_pos > next_group_pos)
256 || (infos_[i].start_moment_ > next_beat_pos))
257 // Find the new group ending point
258 find_location (grouping, options.base_moment_, infos_[i].start_moment_,
259 infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
260 // Mark the start of this beat group
261 if (infos_[i].start_moment_ == group_pos)
262 infos_[i].rhythmic_importance_ = -2;
263 // Work through the end of the beat group or the end of the beam
264 while (i < infos_.size () && infos_[i].start_moment_ < next_group_pos)
266 // Set the tuplet start as necessary
267 update_tuplet (infos_[i].start_moment_, infos_[i].factor_, &tuplet_start_moment);
268 Moment dt = infos_[i].start_moment_ - group_pos;
269 Rational tuplet = infos_[i].factor_;
270 Moment tuplet_moment (tuplet);
271 Moment tuplet_dt = infos_[i].start_moment_ - tuplet_start_moment;
272 tuplet_number = tuplet.den ();
273 // set the beat end and increment the next beat
274 if (infos_[i].start_moment_ == next_beat_pos)
276 infos_[i].rhythmic_importance_ = -1;
277 next_beat_pos += options.base_moment_;
279 // The rhythmic importance of a stem between beats depends on its fraction
280 // of a beat: those stems with a lower denominator are deemed more
281 // important. For tuplets, we need to make sure that we use
282 // the fraction of the tuplet, instead of the fraction of
284 Moment ratio = (tuplet_number == 1)
285 ? dt / options.base_moment_
286 : tuplet_dt / Moment (1, 8) / tuplet_moment;
287 if (infos_[i].rhythmic_importance_ >= 0)
288 infos_[i].rhythmic_importance_ = (int) ratio.den ();
293 if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
295 if (tuplet_number == 1)
296 infos_[i].rhythmic_importance_ = -1;
297 next_beat_pos += options.base_moment_;
298 if (infos_[i].start_moment_ == next_group_pos)
299 infos_[i].rhythmic_importance_ = -2;
305 Invisible stems should be treated as though they have the same number of
306 beams as their least-beamed neighbour. Here we go through the stems and
307 modify the invisible stems to satisfy this requirement.
310 Beaming_pattern::unbeam_invisible_stems ()
312 for (vsize i = 1; i < infos_.size (); i++)
313 if (infos_[i].invisible_)
315 int b = min (infos_[i].count (LEFT), infos_[i - 1].count (LEFT));
316 infos_[i].beam_count_drul_[LEFT] = b;
317 infos_[i].beam_count_drul_[RIGHT] = b;
320 if (infos_.size () > 1)
321 for (vsize i = infos_.size () - 1; i--;)
322 if (infos_[i].invisible_)
324 int b = min (infos_[i].count (LEFT), infos_[i + 1].count (LEFT));
325 infos_[i].beam_count_drul_[LEFT] = b;
326 infos_[i].beam_count_drul_[RIGHT] = b;
331 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor, bool tuplet_start)
333 infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor, tuplet_start));
336 Beaming_pattern::Beaming_pattern ()
341 Beaming_pattern::beamlet_count (int i, Direction d) const
343 return infos_.at (i).beam_count_drul_[d];
347 Beaming_pattern::start_moment (int i) const
349 return infos_.at (i).start_moment_;
353 Beaming_pattern::end_moment (int i) const
355 Duration *dur = new Duration (2 + max (beamlet_count (i, LEFT),
356 beamlet_count (i, RIGHT)),
359 return infos_.at (i).start_moment_ + dur->get_length ();
363 Beaming_pattern::invisibility (int i) const
365 return infos_.at (i).invisible_;
369 Beaming_pattern::factor (int i) const
371 return infos_.at (i).factor_;
375 Beaming_pattern::tuplet_start (int i) const
377 return infos_.at (i).tuplet_start_;
381 Split a beaming pattern at index i and return a new
382 Beaming_pattern containing the removed elements
385 Beaming_pattern::split_pattern (int i)
387 Beaming_pattern *new_pattern = 0;
390 new_pattern = new Beaming_pattern ();
391 for (vsize j = i + 1; j < infos_.size (); j++)
393 count = max (beamlet_count (j, LEFT), beamlet_count (j, RIGHT));
394 new_pattern->add_stem (start_moment (j),
400 for (vsize j = i + 1; j < infos_.size ();)
402 return (new_pattern);
406 Beaming_options::from_context (Context *context)
408 grouping_ = context->get_property ("beatStructure");
409 subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
410 strict_beat_beaming_ = to_boolean (context->get_property ("strictBeatBeaming"));
411 base_moment_ = robust_scm2moment (context->get_property ("baseMoment"),
413 measure_length_ = robust_scm2moment (context->get_property ("measureLength"),
417 Beaming_options::Beaming_options ()
420 subdivide_beams_ = false;
421 strict_beat_beaming_ = false;