2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2011 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)
103 // If all else fails, point the beamlet away from the important moment.
104 return (infos_[i].rhythmic_importance_ <= infos_[i + 1].rhythmic_importance_)
109 Beaming_pattern::de_grace ()
111 for (vsize i = 0; i < infos_.size (); i++)
113 infos_[i].de_grace ();
118 Beaming_pattern::beamify (Beaming_options const &options)
120 if (infos_.size () <= 1)
123 unbeam_invisible_stems ();
125 if (infos_[0].start_moment_.grace_part_)
128 if (infos_[0].start_moment_ < Moment (0))
129 for (vsize i = 0; i < infos_.size (); i++)
130 infos_[i].start_moment_ += options.measure_length_;
132 find_rhythmic_importance (options);
134 vector <Direction> flag_directions;
135 // Get the initial flag directions
136 for (vsize i = 0; i < infos_.size (); i++)
137 flag_directions.push_back (flag_direction (options, i));
139 // Correct flag directions for subdivision
140 for (vsize i = 1; i < infos_.size () - 1; i++)
142 if ((flag_directions[i] == CENTER) && (flag_directions[i - 1] == LEFT))
143 flag_directions[i] = RIGHT;
144 if ((flag_directions[i] == CENTER) && (flag_directions[i + 1] == RIGHT))
145 flag_directions[i] = LEFT;
148 // Set the count on each side of the stem
149 // We need to run this code twice to make both the
150 // left and the right counts work properly
151 for (int i = 0; i < 2; i++)
152 for (vsize i = 1; i < infos_.size () - 1; i++)
154 Direction non_flag_dir = other_dir (flag_directions[i]);
157 int importance = infos_[i + 1].rhythmic_importance_;
158 int count = (importance < 0 && options.subdivide_beams_)
159 ? 1 : min (min (infos_[i].count (non_flag_dir),
160 infos_[i + non_flag_dir].count (-non_flag_dir)),
161 infos_[i - non_flag_dir].count (non_flag_dir));
163 infos_[i].beam_count_drul_[non_flag_dir] = count;
169 Get the group start position, the next group starting position, and the
170 next beat starting position, given start_moment, base_moment,
174 find_location (SCM grouping, Moment base_moment, Moment start_moment,
175 Rational factor, Moment *group_pos, Moment *next_group_pos,
176 Moment *next_beat_pos)
178 *group_pos = Moment (0);
179 *next_group_pos = Moment (0);
180 *next_beat_pos = base_moment;
182 while (*next_beat_pos <= start_moment)
183 *next_beat_pos += base_moment;
185 while (*next_group_pos < *next_beat_pos)
187 int count = 1; //default -- 1 base moments in a beam
188 if (scm_is_pair (grouping))
190 count = scm_to_int (scm_car (grouping));
191 grouping = scm_cdr (grouping);
194 // If we have a tuplet, the count should be determined from
195 // the maximum tuplet size for beamed tuplets.
196 int tuplet_count = factor.num ();
197 if (tuplet_count > 1)
199 // We use 1/8 as the base moment for the tuplet because it's
200 // the largest beamed value. If the tuplet is shorter, it's
201 // OK, the code still works
202 int test_count = (tuplet_count * Moment (Rational (1, 8)) / base_moment).num ();
203 if (test_count > count) count = test_count;
205 *group_pos = *next_group_pos;
206 *next_group_pos = *group_pos + count * base_moment;
211 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
213 Moment group_pos (0); // 0 is the start of the first group
214 Moment next_group_pos (0);
215 Moment next_beat_pos (options.base_moment_);
216 int tuplet_count = 1;
218 SCM grouping = options.grouping_;
221 // Find where we are in the beat structure of the measure
223 find_location (grouping, options.base_moment_, infos_[i].start_moment_,
224 infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
226 // Mark the importance of stems that start at a beat or a beat group.
227 while (i < infos_.size ())
229 tuplet_count = infos_[i].factor_.den ();
230 if ((next_beat_pos > next_group_pos)
231 || (infos_[i].start_moment_ > next_beat_pos))
232 // Find the new group ending point
233 find_location (grouping, options.base_moment_, infos_[i].start_moment_,
234 infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
235 // Mark the start of this beat group
236 if (infos_[i].start_moment_ == group_pos)
237 infos_[i].rhythmic_importance_ = -2;
238 // Work through the end of the beat group or the end of the beam
239 while (i < infos_.size () && infos_[i].start_moment_ < next_group_pos)
241 Moment dt = infos_[i].start_moment_ - group_pos;
242 Rational tuplet = infos_[i].factor_;
243 Moment tuplet_moment (tuplet);
244 // set the beat end (if not in a tuplet) and increment the next beat
245 if (tuplet_count == 1 && infos_[i].start_moment_ == next_beat_pos)
247 infos_[i].rhythmic_importance_ = -1;
248 next_beat_pos += options.base_moment_;
250 // The rhythmic importance of a stem between beats depends on its fraction
251 // of a beat: those stems with a lower denominator are deemed more
252 // important. For tuplets, we need to make sure that we use
253 // the fraction of the tuplet, instead of the fraction of
255 Moment ratio = (dt / options.base_moment_ / tuplet_moment);
256 if (infos_[i].rhythmic_importance_ >= 0)
257 infos_[i].rhythmic_importance_ = (int) ratio.den ();
261 if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
263 if (tuplet_count == 1)
264 infos_[i].rhythmic_importance_ = -1;
265 next_beat_pos += options.base_moment_;
266 if (infos_[i].start_moment_ == next_group_pos)
267 infos_[i].rhythmic_importance_ = -2;
274 Invisible stems should be treated as though they have the same number of
275 beams as their least-beamed neighbour. Here we go through the stems and
276 modify the invisible stems to satisfy this requirement.
279 Beaming_pattern::unbeam_invisible_stems ()
281 for (vsize i = 1; i < infos_.size (); i++)
282 if (infos_[i].invisible_)
284 int b = min (infos_[i].count (LEFT), infos_[i - 1].count (LEFT));
285 infos_[i].beam_count_drul_[LEFT] = b;
286 infos_[i].beam_count_drul_[RIGHT] = b;
289 if (infos_.size () > 1)
290 for (vsize i = infos_.size () - 1; i--;)
291 if (infos_[i].invisible_)
293 int b = min (infos_[i].count (LEFT), infos_[i + 1].count (LEFT));
294 infos_[i].beam_count_drul_[LEFT] = b;
295 infos_[i].beam_count_drul_[RIGHT] = b;
300 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor)
302 infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor));
305 Beaming_pattern::Beaming_pattern ()
310 Beaming_pattern::beamlet_count (int i, Direction d) const
312 return infos_.at (i).beam_count_drul_[d];
316 Beaming_pattern::start_moment (int i) const
318 return infos_.at (i).start_moment_;
322 Beaming_pattern::end_moment (int i) const
324 Duration *dur = new Duration (2 + max (beamlet_count (i, LEFT),
325 beamlet_count (i, RIGHT)),
328 return infos_.at (i).start_moment_ + dur->get_length ();
332 Beaming_pattern::invisibility (int i) const
334 return infos_.at (i).invisible_;
338 Beaming_pattern::factor (int i) const
340 return infos_.at (i).factor_;
344 Split a beaming pattern at index i and return a new
345 Beaming_pattern containing the removed elements
348 Beaming_pattern::split_pattern (int i)
350 Beaming_pattern *new_pattern = 0;
353 new_pattern = new Beaming_pattern ();
354 for (vsize j = i + 1; j < infos_.size (); j++)
356 count = max (beamlet_count (j, LEFT), beamlet_count (j, RIGHT));
357 new_pattern->add_stem (start_moment (j),
362 for (vsize j = i + 1; j < infos_.size ();)
364 return (new_pattern);
368 Beaming_options::from_context (Context *context)
370 grouping_ = context->get_property ("beatStructure");
371 subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
372 base_moment_ = robust_scm2moment (context->get_property ("baseMoment"),
374 measure_length_ = robust_scm2moment (context->get_property ("measureLength"),
378 Beaming_options::Beaming_options ()
381 subdivide_beams_ = false;