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);
46 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv, Rational factor)
49 rhythmic_importance_ = 0;
50 beam_count_drul_[LEFT] = i;
51 beam_count_drul_[RIGHT] = i;
57 Beam_rhythmic_element::de_grace ()
59 if (start_moment_.grace_part_)
61 start_moment_.main_part_ = start_moment_.grace_part_;
62 start_moment_.grace_part_ = 0;
67 Beam_rhythmic_element::count (Direction d) const
69 return beam_count_drul_[d];
73 Finds the appropriate direction for the flags at the given index that
74 hang below the neighbouring flags. If
75 the stem has no more flags than either of its neighbours, this returns
79 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
81 // The extremal stems shouldn't be messed with, so it's appropriate to
82 // return CENTER here also.
83 if (i == 0 || i == infos_.size () - 1)
86 int count = infos_[i].count (LEFT); // Both directions should still be the same
87 int left_count = infos_[i - 1].count (RIGHT);
88 int right_count = infos_[i + 1].count (LEFT);
90 // If we are told to subdivide beams and we are next to a beat, point the
91 // beamlet away from the beat.
92 if (options.subdivide_beams_)
94 if (infos_[i].rhythmic_importance_ < 0)
96 else if (infos_[i + 1].rhythmic_importance_ < 0)
100 if (count <= left_count && count <= right_count)
102 else if (!options.strict_beat_beaming_)
104 // Try to avoid sticking-out flags as much as possible by pointing
105 // my flags at the neighbor with the most flags.
106 if (right_count > left_count)
108 else if (left_count > right_count)
112 // If all else fails, point the beamlet away from the important moment.
113 return (infos_[i].rhythmic_importance_ < infos_[i + 1].rhythmic_importance_)
118 Beaming_pattern::de_grace ()
120 for (vsize i = 0; i < infos_.size (); i++)
122 infos_[i].de_grace ();
127 Beaming_pattern::beamify (Beaming_options const &options)
129 if (infos_.size () <= 1)
132 unbeam_invisible_stems ();
134 if (infos_[0].start_moment_.grace_part_)
137 if (infos_[0].start_moment_ < Moment (0))
138 for (vsize i = 0; i < infos_.size (); i++)
139 infos_[i].start_moment_ += options.measure_length_;
141 find_rhythmic_importance (options);
143 vector <Direction> flag_directions;
144 // Get the initial flag directions
145 for (vsize i = 0; i < infos_.size (); i++)
146 flag_directions.push_back (flag_direction (options, i));
148 // Correct flag directions for subdivision
149 for (vsize i = 1; i < infos_.size () - 1; i++)
151 if ((flag_directions[i] == CENTER) && (flag_directions[i - 1] == LEFT))
152 flag_directions[i] = RIGHT;
153 if ((flag_directions[i] == CENTER) && (flag_directions[i + 1] == RIGHT))
154 flag_directions[i] = LEFT;
157 // Set the count on each side of the stem
158 // We need to run this code twice to make both the
159 // left and the right counts work properly
160 for (int i = 0; i < 2; i++)
161 for (vsize i = 1; i < infos_.size () - 1; i++)
163 Direction non_flag_dir = other_dir (flag_directions[i]);
166 int importance = infos_[i + 1].rhythmic_importance_;
167 int count = (importance < 0 && options.subdivide_beams_)
168 ? 1 : min (min (infos_[i].count (non_flag_dir),
169 infos_[i + non_flag_dir].count (-non_flag_dir)),
170 infos_[i - non_flag_dir].count (non_flag_dir));
172 infos_[i].beam_count_drul_[non_flag_dir] = count;
178 Set the tuplet start moment as necessary
181 update_tuplet (Moment start_moment, Rational factor, Moment *tuplet_start_moment)
183 int tuplet_number = (int) factor.den ();
184 if ((tuplet_number > 1) && (tuplet_start_moment->num () < 0))
185 *tuplet_start_moment = start_moment;
186 else if (tuplet_number == 1)
187 *tuplet_start_moment = Moment (-1, 1);
192 Get the group start position, the next group starting position, and the
193 next beat starting position, given start_moment, base_moment,
197 find_location (SCM grouping, Moment base_moment, Moment start_moment,
198 Rational factor, Moment *group_pos, Moment *next_group_pos,
199 Moment *next_beat_pos)
201 *group_pos = Moment (0);
202 *next_group_pos = Moment (0);
203 *next_beat_pos = base_moment;
205 while (*next_beat_pos <= start_moment)
206 *next_beat_pos += base_moment;
208 while (*next_group_pos < *next_beat_pos)
210 int group_count = 1; //default -- 1 base moments in a beam
211 if (scm_is_pair (grouping))
213 group_count = scm_to_int (scm_car (grouping));
214 grouping = scm_cdr (grouping);
217 // If we have a tuplet, the count should be determined from
218 // the maximum tuplet size for beamed tuplets.
219 int tuplet_number = factor.den ();
220 if (tuplet_number > 1)
222 // We use 1/8 as the base moment for the tuplet because it's
223 // the largest beamed value. If the tuplet is shorter, it's
224 // OK, the code still works
225 int test_count = ( Moment (Rational (1, 8) / factor ) / base_moment).num ();
226 if (test_count > group_count) group_count = test_count;
228 *group_pos = *next_group_pos;
229 *next_group_pos = *group_pos + group_count * base_moment;
234 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
236 Moment group_pos (0); // 0 is the start of the first group
237 Moment next_group_pos (0);
238 Moment next_beat_pos (options.base_moment_);
239 Moment tuplet_start_moment (-1, 1);
240 int tuplet_number = 1;
242 SCM grouping = options.grouping_;
245 // Find where we are in the beat structure of the measure
247 find_location (grouping, options.base_moment_, infos_[i].start_moment_,
248 infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
250 // Mark the importance of stems that start at a beat or a beat group.
251 while (i < infos_.size ())
253 if ((next_beat_pos > next_group_pos)
254 || (infos_[i].start_moment_ > next_beat_pos))
255 // Find the new group ending point
256 find_location (grouping, options.base_moment_, infos_[i].start_moment_,
257 infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
258 // Mark the start of this beat group
259 if (infos_[i].start_moment_ == group_pos)
260 infos_[i].rhythmic_importance_ = -2;
261 // Work through the end of the beat group or the end of the beam
262 while (i < infos_.size () && infos_[i].start_moment_ < next_group_pos)
264 // Set the tuplet start as necessary
265 update_tuplet (infos_[i].start_moment_, infos_[i].factor_, &tuplet_start_moment);
266 Moment dt = infos_[i].start_moment_ - group_pos;
267 Rational tuplet = infos_[i].factor_;
268 Moment tuplet_moment (tuplet);
269 Moment tuplet_dt = infos_[i].start_moment_ - tuplet_start_moment;
270 tuplet_number = tuplet.den ();
271 // set the beat end (if not in a tuplet) and increment the next beat
272 if (tuplet_number == 1 && infos_[i].start_moment_ == next_beat_pos)
274 infos_[i].rhythmic_importance_ = -1;
275 next_beat_pos += options.base_moment_;
277 // The rhythmic importance of a stem between beats depends on its fraction
278 // of a beat: those stems with a lower denominator are deemed more
279 // important. For tuplets, we need to make sure that we use
280 // the fraction of the tuplet, instead of the fraction of
282 Moment ratio = (tuplet_number == 1)
283 ? dt / options.base_moment_
284 : tuplet_dt / Moment (1, 8) / tuplet_moment;
285 if (infos_[i].rhythmic_importance_ >= 0)
286 infos_[i].rhythmic_importance_ = (int) ratio.den ();
291 if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
293 if (tuplet_number == 1)
294 infos_[i].rhythmic_importance_ = -1;
295 next_beat_pos += options.base_moment_;
296 if (infos_[i].start_moment_ == next_group_pos)
297 infos_[i].rhythmic_importance_ = -2;
303 Invisible stems should be treated as though they have the same number of
304 beams as their least-beamed neighbour. Here we go through the stems and
305 modify the invisible stems to satisfy this requirement.
308 Beaming_pattern::unbeam_invisible_stems ()
310 for (vsize i = 1; i < infos_.size (); i++)
311 if (infos_[i].invisible_)
313 int b = min (infos_[i].count (LEFT), infos_[i - 1].count (LEFT));
314 infos_[i].beam_count_drul_[LEFT] = b;
315 infos_[i].beam_count_drul_[RIGHT] = b;
318 if (infos_.size () > 1)
319 for (vsize i = infos_.size () - 1; i--;)
320 if (infos_[i].invisible_)
322 int b = min (infos_[i].count (LEFT), infos_[i + 1].count (LEFT));
323 infos_[i].beam_count_drul_[LEFT] = b;
324 infos_[i].beam_count_drul_[RIGHT] = b;
329 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor)
331 infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor));
334 Beaming_pattern::Beaming_pattern ()
339 Beaming_pattern::beamlet_count (int i, Direction d) const
341 return infos_.at (i).beam_count_drul_[d];
345 Beaming_pattern::start_moment (int i) const
347 return infos_.at (i).start_moment_;
351 Beaming_pattern::end_moment (int i) const
353 Duration *dur = new Duration (2 + max (beamlet_count (i, LEFT),
354 beamlet_count (i, RIGHT)),
357 return infos_.at (i).start_moment_ + dur->get_length ();
361 Beaming_pattern::invisibility (int i) const
363 return infos_.at (i).invisible_;
367 Beaming_pattern::factor (int i) const
369 return infos_.at (i).factor_;
373 Split a beaming pattern at index i and return a new
374 Beaming_pattern containing the removed elements
377 Beaming_pattern::split_pattern (int i)
379 Beaming_pattern *new_pattern = 0;
382 new_pattern = new Beaming_pattern ();
383 for (vsize j = i + 1; j < infos_.size (); j++)
385 count = max (beamlet_count (j, LEFT), beamlet_count (j, RIGHT));
386 new_pattern->add_stem (start_moment (j),
391 for (vsize j = i + 1; j < infos_.size ();)
393 return (new_pattern);
397 Beaming_options::from_context (Context *context)
399 grouping_ = context->get_property ("beatStructure");
400 subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
401 strict_beat_beaming_ = to_boolean (context->get_property ("strictBeatBeaming"));
402 base_moment_ = robust_scm2moment (context->get_property ("baseMoment"),
404 measure_length_ = robust_scm2moment (context->get_property ("measureLength"),
408 Beaming_options::Beaming_options ()
411 subdivide_beams_ = false;
412 strict_beat_beaming_ = false;