]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-pattern.cc
Release: update news.
[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 count =
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)
179
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));
184
185             // Ensure at least one beam is left, even for groups longer than 1/8
186             count = max (count, 1);
187
188             infos_[i].beam_count_drul_[non_flag_dir] = count;
189           }
190       }
191 }
192
193 /*
194    Set the tuplet start moment as necessary
195 */
196 void
197 update_tuplet (Moment start_moment, Rational factor, Moment *tuplet_start_moment)
198 {
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);
204 }
205
206 /*
207    Get the group start position, the next group starting position, and the
208    next beat starting position, given start_moment, base_moment,
209    grouping, and factor
210 */
211 void
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)
215 {
216   *group_pos = Moment (0);
217   *next_group_pos = Moment (0);
218   *next_beat_pos = base_moment;
219
220   while (*next_beat_pos <= start_moment)
221     *next_beat_pos += base_moment;
222
223   while (*next_group_pos < *next_beat_pos)
224     {
225       I64 group_count = 1;  //default -- 1 base moments in a beam
226       if (scm_is_pair (grouping))
227         {
228           group_count = scm_to_int (scm_car (grouping));
229           grouping = scm_cdr (grouping);
230         }
231
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)
236         {
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;
242         }
243       *group_pos = *next_group_pos;
244       *next_group_pos = *group_pos + Rational(group_count) * base_moment;
245     }
246 }
247
248 void
249 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
250 {
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;
256
257   SCM grouping = options.grouping_;
258   vsize i = 0;
259
260   // Find where we are in the beat structure of the measure
261   if (infos_.size ())
262     find_location (grouping, options.base_moment_, infos_[i].start_moment_,
263                    infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
264
265   // Mark the importance of stems that start at a beat or a beat group.
266   while (i < infos_.size ())
267     {
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)
278         {
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)
288             {
289               infos_[i].rhythmic_importance_ = -1;
290               next_beat_pos += options.base_moment_;
291             }
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
296           // a beat.
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 ();
302
303           i++;
304         }
305
306       if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
307         {
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;
313         }
314     }
315 }
316
317 /*
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.
321 */
322 void
323 Beaming_pattern::unbeam_invisible_stems ()
324 {
325   for (vsize i = 1; i < infos_.size (); i++)
326     if (infos_[i].invisible_)
327       {
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;
331       }
332
333   if (infos_.size () > 1)
334     for (vsize i = infos_.size () - 1; i--;)
335       if (infos_[i].invisible_)
336         {
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;
340         }
341 }
342
343 void
344 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor, bool tuplet_start)
345 {
346   infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor, tuplet_start));
347 }
348
349 Beaming_pattern::Beaming_pattern ()
350 {
351 }
352
353 int
354 Beaming_pattern::beamlet_count (int i, Direction d) const
355 {
356   return infos_.at (i).beam_count_drul_[d];
357 }
358
359 Moment
360 Beaming_pattern::start_moment (int i) const
361 {
362   return infos_.at (i).start_moment_;
363 }
364
365 Moment
366 Beaming_pattern::end_moment (int i) const
367 {
368   Duration dur (2 + max (beamlet_count (i, LEFT),
369                          beamlet_count (i, RIGHT)),
370                 0);
371
372   return infos_.at (i).start_moment_
373          + infos_.at (i).factor_ * dur.get_length ();
374 }
375
376 Moment
377 Beaming_pattern::remaining_length (int i) const
378 {
379     return end_moment (infos_.size () - 1) - infos_[i].start_moment_;
380 }
381
382 int
383 Beaming_pattern::beam_count_for_rhythmic_position (int idx) const
384 {
385     // Calculate number of beams representing the rhythmic position of given stem
386     return intlog2(infos_[idx].start_moment_.main_part_.den()) - 2;
387 }
388
389 int
390 Beaming_pattern::beam_count_for_length (Moment len) const
391 {
392     return intlog2(len.main_part_.den()) - 2 - intlog2(len.main_part_.num());
393 }
394
395 bool
396 Beaming_pattern::invisibility (int i) const
397 {
398   return infos_.at (i).invisible_;
399 }
400
401 Rational
402 Beaming_pattern::factor (int i) const
403 {
404   return infos_.at (i).factor_;
405 }
406
407 bool
408 Beaming_pattern::tuplet_start (int i) const
409 {
410   return infos_.at (i).tuplet_start_;
411 }
412
413 /*
414     Split a beaming pattern at index i and return a new
415     Beaming_pattern containing the removed elements
416 */
417 Beaming_pattern *
418 Beaming_pattern::split_pattern (int i)
419 {
420   Beaming_pattern *new_pattern = 0;
421   int count;
422
423   new_pattern = new Beaming_pattern ();
424   for (vsize j = i + 1; j < infos_.size (); j++)
425     {
426       count = max (beamlet_count (j, LEFT), beamlet_count (j, RIGHT));
427       new_pattern->add_stem (start_moment (j),
428                              count,
429                              invisibility (j),
430                              factor (j),
431                              tuplet_start (j));
432     }
433   for (vsize j = i + 1; j < infos_.size ();)
434     infos_.pop_back ();
435   return (new_pattern);
436 }
437
438 void
439 Beaming_options::from_context (Context *context)
440 {
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"),
445                                     Moment (1, 4));
446   measure_length_ = robust_scm2moment (context->get_property ("measureLength"),
447                                        Moment (4, 4));
448 }
449
450 Beaming_options::Beaming_options ()
451 {
452   grouping_ = SCM_EOL;
453   subdivide_beams_ = false;
454   strict_beat_beaming_ = false;
455 }