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