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