]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-pattern.cc
Merge branch 'master' into lilypond/translation
[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 and increment the next beat
274           if (infos_[i].start_moment_ == next_beat_pos)
275             {
276               infos_[i].rhythmic_importance_ = -1;
277               next_beat_pos += options.base_moment_;
278             }
279           // The rhythmic importance of a stem between beats depends on its fraction
280           // of a beat: those stems with a lower denominator are deemed more
281           // important.  For tuplets, we need to make sure that we use
282           // the fraction of the tuplet, instead of the fraction of
283           // a beat.
284           Moment ratio = (tuplet_number == 1)
285                            ? dt / options.base_moment_
286                            : tuplet_dt / Moment (1, 8)  / tuplet_moment;
287           if (infos_[i].rhythmic_importance_ >= 0)
288             infos_[i].rhythmic_importance_ = (int) ratio.den ();
289
290           i++;
291         }
292
293       if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
294         {
295           if (tuplet_number == 1)
296             infos_[i].rhythmic_importance_ = -1;
297           next_beat_pos += options.base_moment_;
298           if (infos_[i].start_moment_ == next_group_pos)
299             infos_[i].rhythmic_importance_ = -2;
300         }
301     }
302 }
303
304 /*
305   Invisible stems should be treated as though they have the same number of
306   beams as their least-beamed neighbour. Here we go through the stems and
307   modify the invisible stems to satisfy this requirement.
308 */
309 void
310 Beaming_pattern::unbeam_invisible_stems ()
311 {
312   for (vsize i = 1; i < infos_.size (); i++)
313     if (infos_[i].invisible_)
314       {
315         int b = min (infos_[i].count (LEFT), infos_[i - 1].count (LEFT));
316         infos_[i].beam_count_drul_[LEFT] = b;
317         infos_[i].beam_count_drul_[RIGHT] = b;
318       }
319
320   if (infos_.size () > 1)
321     for (vsize i = infos_.size () - 1; i--;)
322       if (infos_[i].invisible_)
323         {
324           int b = min (infos_[i].count (LEFT), infos_[i + 1].count (LEFT));
325           infos_[i].beam_count_drul_[LEFT] = b;
326           infos_[i].beam_count_drul_[RIGHT] = b;
327         }
328 }
329
330 void
331 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor, bool tuplet_start)
332 {
333   infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor, tuplet_start));
334 }
335
336 Beaming_pattern::Beaming_pattern ()
337 {
338 }
339
340 int
341 Beaming_pattern::beamlet_count (int i, Direction d) const
342 {
343   return infos_.at (i).beam_count_drul_[d];
344 }
345
346 Moment
347 Beaming_pattern::start_moment (int i) const
348 {
349   return infos_.at (i).start_moment_;
350 }
351
352 Moment
353 Beaming_pattern::end_moment (int i) const
354 {
355   Duration *dur = new Duration (2 + max (beamlet_count (i, LEFT),
356                                          beamlet_count (i, RIGHT)),
357                                 0);
358
359   return infos_.at (i).start_moment_ + 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 }