]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-pattern.cc
4704: Partially revert 0382ed88: "Adjust beam subdivision"
[lilypond.git] / lily / beaming-pattern.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1999--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
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.
10
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.
15
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/>.
18 */
19
20 #include "context.hh"
21 #include "beaming-pattern.hh"
22 #include "misc.hh"
23
24 /*
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.
27
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.
35 */
36 Beam_rhythmic_element::Beam_rhythmic_element ()
37 {
38   start_moment_ = 0;
39   rhythmic_importance_ = 0;
40   beam_count_drul_[LEFT] = 0;
41   beam_count_drul_[RIGHT] = 0;
42   invisible_ = false;
43   factor_ = Rational (1);
44   tuplet_start_ = false;
45 }
46
47 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv,
48                                               Rational factor, bool tuplet_start)
49 {
50   start_moment_ = m;
51   rhythmic_importance_ = 0;
52   beam_count_drul_[LEFT] = i;
53   beam_count_drul_[RIGHT] = i;
54   invisible_ = inv;
55   factor_ = factor;
56   tuplet_start_ = tuplet_start;
57 }
58
59 void
60 Beam_rhythmic_element::de_grace ()
61 {
62   if (start_moment_.grace_part_)
63     {
64       start_moment_.main_part_ = start_moment_.grace_part_;
65       start_moment_.grace_part_ = 0;
66     }
67 }
68
69 int
70 Beam_rhythmic_element::count (Direction d) const
71 {
72   return beam_count_drul_[d];
73 }
74
75 /*
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
79   CENTER.
80 */
81 Direction
82 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
83 {
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)
87     return CENTER;
88
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);
92
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_)
96     {
97       if (infos_[i].rhythmic_importance_ < 0)
98         return RIGHT;
99       else if (infos_[i + 1].rhythmic_importance_ < 0)
100         return LEFT;
101     }
102
103   if (count <= left_count && count <= right_count)
104     return CENTER;
105   else if (!options.strict_beat_beaming_)
106     {
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)
110         return RIGHT;
111       else if (left_count > right_count)
112         return LEFT;
113     }
114
115   // If all else fails, point the beamlet away from the important moment.
116   return (infos_[i].rhythmic_importance_ < infos_[i + 1].rhythmic_importance_)
117          ? RIGHT : LEFT;
118 }
119
120 void
121 Beaming_pattern::de_grace ()
122 {
123   for (vsize i = 0; i < infos_.size (); i++)
124     {
125       infos_[i].de_grace ();
126     }
127 }
128
129 void
130 Beaming_pattern::beamify (Beaming_options const &options)
131 {
132   if (infos_.size () <= 1)
133     return;
134
135   unbeam_invisible_stems ();
136
137   if (infos_[0].start_moment_.grace_part_)
138     de_grace ();
139
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_;
143
144   find_rhythmic_importance (options);
145
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));
150
151   // Correct flag directions for subdivision
152   for (vsize i = 1; i < infos_.size () - 1; i++)
153     {
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;
158     }
159
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++)
165       {
166         Direction non_flag_dir = -flag_directions[i];
167         if (non_flag_dir)
168           {
169             int importance = infos_[i + 1].rhythmic_importance_;
170             int start_dur = intlog2(infos_[i+1].start_moment_.main_part_.den());
171             int count = (importance < 0 && options.subdivide_beams_) 
172                         ? max(start_dur,3)-2 // 1/8 note has one beam
173                         : min (min (infos_[i].count (non_flag_dir),
174                                         infos_[i + non_flag_dir].count (-non_flag_dir)),
175                                    infos_[i - non_flag_dir].count (non_flag_dir));
176
177             infos_[i].beam_count_drul_[non_flag_dir] = max(count, 1);
178           }
179       }
180 }
181
182 /*
183    Set the tuplet start moment as necessary
184 */
185 void
186 update_tuplet (Moment start_moment, Rational factor, Moment *tuplet_start_moment)
187 {
188   int tuplet_number = (int) factor.den ();
189   if ((tuplet_number > 1) && (tuplet_start_moment->num () < 0))
190     *tuplet_start_moment = start_moment;
191   else if (tuplet_number == 1)
192     *tuplet_start_moment = Moment (-1, 1);
193 }
194
195 /*
196    Get the group start position, the next group starting position, and the
197    next beat starting position, given start_moment, base_moment,
198    grouping, and factor
199 */
200 void
201 find_location (SCM grouping, Moment base_moment, Moment start_moment,
202                Rational factor, Moment *group_pos, Moment *next_group_pos,
203                Moment *next_beat_pos)
204 {
205   *group_pos = Moment (0);
206   *next_group_pos = Moment (0);
207   *next_beat_pos = base_moment;
208
209   while (*next_beat_pos <= start_moment)
210     *next_beat_pos += base_moment;
211
212   while (*next_group_pos < *next_beat_pos)
213     {
214       I64 group_count = 1;  //default -- 1 base moments in a beam
215       if (scm_is_pair (grouping))
216         {
217           group_count = scm_to_int (scm_car (grouping));
218           grouping = scm_cdr (grouping);
219         }
220
221       // If we have a tuplet, the count should be determined from
222       // the maximum tuplet size for beamed tuplets.
223       U64 tuplet_number = factor.den ();
224       if (tuplet_number > 1U)
225         {
226           // We use 1/8 as the base moment for the tuplet because it's
227           // the largest beamed value.  If the tuplet is shorter, it's
228           // OK, the code still works
229           I64 test_count = ( Moment (Rational (1, 8) / factor) / base_moment).num ();
230           if (test_count > group_count) group_count = test_count;
231         }
232       *group_pos = *next_group_pos;
233       *next_group_pos = *group_pos + Rational(group_count) * base_moment;
234     }
235 }
236
237 void
238 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
239 {
240   Moment group_pos (0);  // 0 is the start of the first group
241   Moment next_group_pos (0);
242   Moment next_beat_pos (options.base_moment_);
243   Moment tuplet_start_moment (-1, 1);
244   I64 tuplet_number = 1;
245
246   SCM grouping = options.grouping_;
247   vsize i = 0;
248
249   // Find where we are in the beat structure of the measure
250   if (infos_.size ())
251     find_location (grouping, options.base_moment_, infos_[i].start_moment_,
252                    infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
253
254   // Mark the importance of stems that start at a beat or a beat group.
255   while (i < infos_.size ())
256     {
257       if ((next_beat_pos > next_group_pos)
258           || (infos_[i].start_moment_ > next_beat_pos))
259         // Find the new group ending point
260         find_location (grouping, options.base_moment_, infos_[i].start_moment_,
261                        infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
262       // Mark the start of this beat group
263       if (infos_[i].start_moment_ == group_pos)
264         infos_[i].rhythmic_importance_ = -2;
265       // Work through the end of the beat group or the end of the beam
266       while (i < infos_.size () && infos_[i].start_moment_ < next_group_pos)
267         {
268           // Set the tuplet start as necessary
269           update_tuplet (infos_[i].start_moment_, infos_[i].factor_, &tuplet_start_moment);
270           Moment dt = infos_[i].start_moment_ - group_pos;
271           Rational tuplet = infos_[i].factor_;
272           Moment tuplet_moment (tuplet);
273           Moment tuplet_dt = infos_[i].start_moment_ - tuplet_start_moment;
274           tuplet_number = tuplet.den ();
275           // set the beat end and increment the next beat
276           if (infos_[i].start_moment_ == next_beat_pos)
277             {
278               infos_[i].rhythmic_importance_ = -1;
279               next_beat_pos += options.base_moment_;
280             }
281           // The rhythmic importance of a stem between beats depends on its fraction
282           // of a beat: those stems with a lower denominator are deemed more
283           // important.  For tuplets, we need to make sure that we use
284           // the fraction of the tuplet, instead of the fraction of
285           // a beat.
286           Moment ratio = (tuplet_number == 1)
287                          ? dt / options.base_moment_
288                          : tuplet_dt / Moment (1, 8) / tuplet_moment;
289           if (infos_[i].rhythmic_importance_ >= 0)
290             infos_[i].rhythmic_importance_ = (int) ratio.den ();
291
292           i++;
293         }
294
295       if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
296         {
297           if (tuplet_number == 1)
298             infos_[i].rhythmic_importance_ = -1;
299           next_beat_pos += options.base_moment_;
300           if (infos_[i].start_moment_ == next_group_pos)
301             infos_[i].rhythmic_importance_ = -2;
302         }
303     }
304 }
305
306 /*
307   Invisible stems should be treated as though they have the same number of
308   beams as their least-beamed neighbour. Here we go through the stems and
309   modify the invisible stems to satisfy this requirement.
310 */
311 void
312 Beaming_pattern::unbeam_invisible_stems ()
313 {
314   for (vsize i = 1; i < infos_.size (); i++)
315     if (infos_[i].invisible_)
316       {
317         int b = min (infos_[i].count (LEFT), infos_[i - 1].count (LEFT));
318         infos_[i].beam_count_drul_[LEFT] = b;
319         infos_[i].beam_count_drul_[RIGHT] = b;
320       }
321
322   if (infos_.size () > 1)
323     for (vsize i = infos_.size () - 1; i--;)
324       if (infos_[i].invisible_)
325         {
326           int b = min (infos_[i].count (LEFT), infos_[i + 1].count (LEFT));
327           infos_[i].beam_count_drul_[LEFT] = b;
328           infos_[i].beam_count_drul_[RIGHT] = b;
329         }
330 }
331
332 void
333 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor, bool tuplet_start)
334 {
335   infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor, tuplet_start));
336 }
337
338 Beaming_pattern::Beaming_pattern ()
339 {
340 }
341
342 int
343 Beaming_pattern::beamlet_count (int i, Direction d) const
344 {
345   return infos_.at (i).beam_count_drul_[d];
346 }
347
348 Moment
349 Beaming_pattern::start_moment (int i) const
350 {
351   return infos_.at (i).start_moment_;
352 }
353
354 Moment
355 Beaming_pattern::end_moment (int i) const
356 {
357   Duration dur (2 + max (beamlet_count (i, LEFT),
358                          beamlet_count (i, RIGHT)),
359                 0);
360
361   return infos_.at (i).start_moment_
362          + infos_.at (i).factor_ * dur.get_length ();
363 }
364
365 bool
366 Beaming_pattern::invisibility (int i) const
367 {
368   return infos_.at (i).invisible_;
369 }
370
371 Rational
372 Beaming_pattern::factor (int i) const
373 {
374   return infos_.at (i).factor_;
375 }
376
377 bool
378 Beaming_pattern::tuplet_start (int i) const
379 {
380   return infos_.at (i).tuplet_start_;
381 }
382
383 /*
384     Split a beaming pattern at index i and return a new
385     Beaming_pattern containing the removed elements
386 */
387 Beaming_pattern *
388 Beaming_pattern::split_pattern (int i)
389 {
390   Beaming_pattern *new_pattern = 0;
391   int count;
392
393   new_pattern = new Beaming_pattern ();
394   for (vsize j = i + 1; j < infos_.size (); j++)
395     {
396       count = max (beamlet_count (j, LEFT), beamlet_count (j, RIGHT));
397       new_pattern->add_stem (start_moment (j),
398                              count,
399                              invisibility (j),
400                              factor (j),
401                              tuplet_start (j));
402     }
403   for (vsize j = i + 1; j < infos_.size ();)
404     infos_.pop_back ();
405   return (new_pattern);
406 }
407
408 void
409 Beaming_options::from_context (Context *context)
410 {
411   grouping_ = context->get_property ("beatStructure");
412   subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
413   strict_beat_beaming_ = to_boolean (context->get_property ("strictBeatBeaming"));
414   base_moment_ = robust_scm2moment (context->get_property ("baseMoment"),
415                                     Moment (1, 4));
416   measure_length_ = robust_scm2moment (context->get_property ("measureLength"),
417                                        Moment (4, 4));
418 }
419
420 Beaming_options::Beaming_options ()
421 {
422   grouping_ = SCM_EOL;
423   subdivide_beams_ = false;
424   strict_beat_beaming_ = false;
425 }