]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-pattern.cc
088cdc1a65663ccdf907cb18afe26aa48c46c1a4
[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    Get the group start position, the next group starting position, and the
194    next beat starting position, given start_moment, base_moment,
195    grouping, and factor
196 */
197 void
198 find_location (SCM grouping, Moment base_moment, Moment start_moment,
199                Rational factor, Moment *group_pos, Moment *next_group_pos,
200                Moment *next_beat_pos)
201 {
202   *group_pos = Moment (0);
203   *next_group_pos = Moment (0);
204   *next_beat_pos = base_moment;
205
206   while (*next_beat_pos <= start_moment)
207     *next_beat_pos += base_moment;
208
209   while (*next_group_pos < *next_beat_pos)
210     {
211       I64 group_count = 1;  //default -- 1 base moments in a beam
212       if (scm_is_pair (grouping))
213         {
214           group_count = scm_to_int (scm_car (grouping));
215           grouping = scm_cdr (grouping);
216         }
217
218       // If we have a tuplet, the count should be determined from
219       // the maximum tuplet size for beamed tuplets.
220       U64 tuplet_number = factor.den ();
221       if (tuplet_number > 1U)
222         {
223           // We use 1/8 as the base moment for the tuplet because it's
224           // the largest beamed value.  If the tuplet is shorter, it's
225           // OK, the code still works
226           I64 test_count = ( Moment (Rational (1, 8) / factor) / base_moment).num ();
227           if (test_count > group_count) group_count = test_count;
228         }
229       *group_pos = *next_group_pos;
230       *next_group_pos = *group_pos + Rational(group_count) * base_moment;
231     }
232 }
233
234 void
235 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
236 {
237   Moment group_pos (0);  // 0 is the start of the first group
238   Moment next_group_pos (0);
239   Moment next_beat_pos (options.base_moment_);
240   Moment tuplet_start_moment (-1, 1);
241   I64 tuplet_number = 1;
242
243   SCM grouping = options.grouping_;
244   vsize i = 0;
245
246   // Find where we are in the beat structure of the measure
247   if (infos_.size ())
248     find_location (grouping, options.base_moment_, infos_[i].start_moment_,
249                    infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
250
251   // Mark the importance of stems that start at a beat or a beat group.
252   while (i < infos_.size ())
253     {
254       if ((next_beat_pos > next_group_pos)
255           || (infos_[i].start_moment_ > next_beat_pos))
256         // Find the new group ending point
257         find_location (grouping, options.base_moment_, infos_[i].start_moment_,
258                        infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
259       // Mark the start of this beat group
260       if (infos_[i].start_moment_ == group_pos)
261         infos_[i].rhythmic_importance_ = -2;
262       // Work through the end of the beat group or the end of the beam
263       while (i < infos_.size () && infos_[i].start_moment_ < next_group_pos)
264         {
265           // Set the tuplet start as necessary
266           update_tuplet (infos_[i].start_moment_, infos_[i].factor_, &tuplet_start_moment);
267           Moment dt = infos_[i].start_moment_ - group_pos;
268           Rational tuplet = infos_[i].factor_;
269           Moment tuplet_moment (tuplet);
270           Moment tuplet_dt = infos_[i].start_moment_ - tuplet_start_moment;
271           tuplet_number = tuplet.den ();
272           // set the beat end and increment the next beat
273           if (infos_[i].start_moment_ == next_beat_pos)
274             {
275               infos_[i].rhythmic_importance_ = -1;
276               next_beat_pos += options.base_moment_;
277             }
278           // The rhythmic importance of a stem between beats depends on its fraction
279           // of a beat: those stems with a lower denominator are deemed more
280           // important.  For tuplets, we need to make sure that we use
281           // the fraction of the tuplet, instead of the fraction of
282           // a beat.
283           Moment ratio = (tuplet_number == 1)
284                          ? dt / options.base_moment_
285                          : tuplet_dt / Moment (1, 8) / tuplet_moment;
286           if (infos_[i].rhythmic_importance_ >= 0)
287             infos_[i].rhythmic_importance_ = (int) ratio.den ();
288
289           i++;
290         }
291
292       if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
293         {
294           if (tuplet_number == 1)
295             infos_[i].rhythmic_importance_ = -1;
296           next_beat_pos += options.base_moment_;
297           if (infos_[i].start_moment_ == next_group_pos)
298             infos_[i].rhythmic_importance_ = -2;
299         }
300     }
301 }
302
303 /*
304   Invisible stems should be treated as though they have the same number of
305   beams as their least-beamed neighbour. Here we go through the stems and
306   modify the invisible stems to satisfy this requirement.
307 */
308 void
309 Beaming_pattern::unbeam_invisible_stems ()
310 {
311   for (vsize i = 1; i < infos_.size (); i++)
312     if (infos_[i].invisible_)
313       {
314         int b = min (infos_[i].count (LEFT), infos_[i - 1].count (LEFT));
315         infos_[i].beam_count_drul_[LEFT] = b;
316         infos_[i].beam_count_drul_[RIGHT] = b;
317       }
318
319   if (infos_.size () > 1)
320     for (vsize i = infos_.size () - 1; i--;)
321       if (infos_[i].invisible_)
322         {
323           int b = min (infos_[i].count (LEFT), infos_[i + 1].count (LEFT));
324           infos_[i].beam_count_drul_[LEFT] = b;
325           infos_[i].beam_count_drul_[RIGHT] = b;
326         }
327 }
328
329 void
330 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor, bool tuplet_start)
331 {
332   infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor, tuplet_start));
333 }
334
335 Beaming_pattern::Beaming_pattern ()
336 {
337 }
338
339 int
340 Beaming_pattern::beamlet_count (int i, Direction d) const
341 {
342   return infos_.at (i).beam_count_drul_[d];
343 }
344
345 Moment
346 Beaming_pattern::start_moment (int i) const
347 {
348   return infos_.at (i).start_moment_;
349 }
350
351 Moment
352 Beaming_pattern::end_moment (int i) const
353 {
354   Duration dur (2 + max (beamlet_count (i, LEFT),
355                          beamlet_count (i, RIGHT)),
356                 0);
357
358   return infos_.at (i).start_moment_
359          + infos_.at (i).factor_ * dur.get_length ();
360 }
361
362 bool
363 Beaming_pattern::invisibility (int i) const
364 {
365   return infos_.at (i).invisible_;
366 }
367
368 Rational
369 Beaming_pattern::factor (int i) const
370 {
371   return infos_.at (i).factor_;
372 }
373
374 bool
375 Beaming_pattern::tuplet_start (int i) const
376 {
377   return infos_.at (i).tuplet_start_;
378 }
379
380 /*
381     Split a beaming pattern at index i and return a new
382     Beaming_pattern containing the removed elements
383 */
384 Beaming_pattern *
385 Beaming_pattern::split_pattern (int i)
386 {
387   Beaming_pattern *new_pattern = 0;
388   int count;
389
390   new_pattern = new Beaming_pattern ();
391   for (vsize j = i + 1; j < infos_.size (); j++)
392     {
393       count = max (beamlet_count (j, LEFT), beamlet_count (j, RIGHT));
394       new_pattern->add_stem (start_moment (j),
395                              count,
396                              invisibility (j),
397                              factor (j),
398                              tuplet_start (j));
399     }
400   for (vsize j = i + 1; j < infos_.size ();)
401     infos_.pop_back ();
402   return (new_pattern);
403 }
404
405 void
406 Beaming_options::from_context (Context *context)
407 {
408   grouping_ = context->get_property ("beatStructure");
409   subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
410   strict_beat_beaming_ = to_boolean (context->get_property ("strictBeatBeaming"));
411   base_moment_ = robust_scm2moment (context->get_property ("baseMoment"),
412                                     Moment (1, 4));
413   measure_length_ = robust_scm2moment (context->get_property ("measureLength"),
414                                        Moment (4, 4));
415 }
416
417 Beaming_options::Beaming_options ()
418 {
419   grouping_ = SCM_EOL;
420   subdivide_beams_ = false;
421   strict_beat_beaming_ = false;
422 }