]> 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
44 }
45
46 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv, Rational factor)
47 {
48   start_moment_ = m;
49   rhythmic_importance_ = 0;
50   beam_count_drul_[LEFT] = i;
51   beam_count_drul_[RIGHT] = i;
52   invisible_ = inv;
53   factor_ = factor;
54 }
55
56 void
57 Beam_rhythmic_element::de_grace ()
58 {
59   if (start_moment_.grace_part_)
60     {
61       start_moment_.main_part_ = start_moment_.grace_part_;
62       start_moment_.grace_part_ = 0;
63     }
64 }
65
66 int
67 Beam_rhythmic_element::count (Direction d) const
68 {
69   return beam_count_drul_[d];
70 }
71
72 /*
73   Finds the appropriate direction for the flags at the given index that
74   hang below the neighbouring flags. If
75   the stem has no more flags than either of its neighbours, this returns
76   CENTER.
77 */
78 Direction
79 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
80 {
81   // The extremal stems shouldn't be messed with, so it's appropriate to
82   // return CENTER here also.
83   if (i == 0 || i == infos_.size () - 1)
84     return CENTER;
85
86   int count = infos_[i].count (LEFT); // Both directions should still be the same
87   int left_count = infos_[i - 1].count (RIGHT);
88   int right_count = infos_[i + 1].count (LEFT);
89
90   // If we are told to subdivide beams and we are next to a beat, point the
91   // beamlet away from the beat.
92   if (options.subdivide_beams_)
93     {
94       if (infos_[i].rhythmic_importance_ < 0)
95         return RIGHT;
96       else if (infos_[i + 1].rhythmic_importance_ < 0)
97         return LEFT;
98     }
99
100   if (count <= left_count && count <= right_count)
101     return CENTER;
102   else if (!options.strict_beat_beaming_)
103     {
104       // Try to avoid sticking-out flags as much as possible by pointing
105       // my flags at the neighbor with the most flags.
106       if (right_count > left_count)
107         return RIGHT;
108       else if (left_count > right_count)
109         return LEFT;
110     }
111
112   // If all else fails, point the beamlet away from the important moment.
113   return (infos_[i].rhythmic_importance_ < infos_[i + 1].rhythmic_importance_)
114          ? RIGHT : LEFT;
115 }
116
117 void
118 Beaming_pattern::de_grace ()
119 {
120   for (vsize i = 0; i < infos_.size (); i++)
121     {
122       infos_[i].de_grace ();
123     }
124 }
125
126 void
127 Beaming_pattern::beamify (Beaming_options const &options)
128 {
129   if (infos_.size () <= 1)
130     return;
131
132   unbeam_invisible_stems ();
133
134   if (infos_[0].start_moment_.grace_part_)
135     de_grace ();
136
137   if (infos_[0].start_moment_ < Moment (0))
138     for (vsize i = 0; i < infos_.size (); i++)
139       infos_[i].start_moment_ += options.measure_length_;
140
141   find_rhythmic_importance (options);
142
143   vector <Direction> flag_directions;
144   // Get the initial flag directions
145   for (vsize i = 0; i < infos_.size (); i++)
146     flag_directions.push_back (flag_direction (options, i));
147
148   // Correct flag directions for subdivision
149   for (vsize i = 1; i < infos_.size () - 1; i++)
150     {
151       if ((flag_directions[i] == CENTER) && (flag_directions[i - 1] == LEFT))
152         flag_directions[i] = RIGHT;
153       if ((flag_directions[i] == CENTER) && (flag_directions[i + 1] == RIGHT))
154         flag_directions[i] = LEFT;
155     }
156
157   // Set the count on each side of the stem
158   // We need to run this code twice to make both the
159   // left and the right counts work properly
160   for (int i = 0; i < 2; i++)
161     for (vsize i = 1; i < infos_.size () - 1; i++)
162       {
163         Direction non_flag_dir = other_dir (flag_directions[i]);
164         if (non_flag_dir)
165           {
166             int importance = infos_[i + 1].rhythmic_importance_;
167             int count = (importance < 0 && options.subdivide_beams_)
168                         ? 1 : min (min (infos_[i].count (non_flag_dir),
169                                         infos_[i + non_flag_dir].count (-non_flag_dir)),
170                                    infos_[i - non_flag_dir].count (non_flag_dir));
171
172             infos_[i].beam_count_drul_[non_flag_dir] = count;
173           }
174       }
175 }
176
177 /*
178    Set the tuplet start moment as necessary
179 */
180 void
181 update_tuplet (Moment start_moment, Rational factor, Moment *tuplet_start_moment)
182 {
183   int tuplet_number = (int) factor.den ();
184   if ((tuplet_number > 1) && (tuplet_start_moment->num () < 0))
185     *tuplet_start_moment = start_moment;
186   else if (tuplet_number == 1)
187     *tuplet_start_moment = Moment (-1, 1);
188 }
189
190
191 /*
192    Get the group start position, the next group starting position, and the
193    next beat starting position, given start_moment, base_moment,
194    grouping, and factor
195 */
196 void
197 find_location (SCM grouping, Moment base_moment, Moment start_moment,
198                Rational factor, Moment *group_pos, Moment *next_group_pos,
199                Moment *next_beat_pos)
200 {
201   *group_pos = Moment (0);
202   *next_group_pos = Moment (0);
203   *next_beat_pos = base_moment;
204
205   while (*next_beat_pos <= start_moment)
206     *next_beat_pos += base_moment;
207
208   while (*next_group_pos < *next_beat_pos)
209     {
210       int group_count = 1;  //default -- 1 base moments in a beam
211       if (scm_is_pair (grouping))
212         {
213           group_count = scm_to_int (scm_car (grouping));
214           grouping = scm_cdr (grouping);
215         }
216
217       // If we have a tuplet, the count should be determined from
218       // the maximum tuplet size for beamed tuplets.
219       int tuplet_number = factor.den ();
220       if (tuplet_number > 1)
221         {
222           // We use 1/8 as the base moment for the tuplet because it's
223           // the largest beamed value.  If the tuplet is shorter, it's
224           // OK, the code still works
225           int test_count = ( Moment (Rational (1, 8) / factor ) / base_moment).num ();
226           if (test_count > group_count) group_count = test_count;
227         }
228       *group_pos = *next_group_pos;
229       *next_group_pos = *group_pos + group_count * base_moment;
230     }
231 }
232
233 void
234 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
235 {
236   Moment group_pos (0);  // 0 is the start of the first group
237   Moment next_group_pos (0);
238   Moment next_beat_pos (options.base_moment_);
239   Moment tuplet_start_moment (-1, 1);
240   int tuplet_number = 1;
241
242   SCM grouping = options.grouping_;
243   vsize i = 0;
244
245   // Find where we are in the beat structure of the measure
246   if (infos_.size ())
247     find_location (grouping, options.base_moment_, infos_[i].start_moment_,
248                    infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
249
250   // Mark the importance of stems that start at a beat or a beat group.
251   while (i < infos_.size ())
252     {
253       if ((next_beat_pos > next_group_pos)
254           || (infos_[i].start_moment_ > next_beat_pos))
255         // Find the new group ending point
256         find_location (grouping, options.base_moment_, infos_[i].start_moment_,
257                        infos_[i].factor_, &group_pos, &next_group_pos, &next_beat_pos);
258       // Mark the start of this beat group
259       if (infos_[i].start_moment_ == group_pos)
260         infos_[i].rhythmic_importance_ = -2;
261       // Work through the end of the beat group or the end of the beam
262       while (i < infos_.size () && infos_[i].start_moment_ < next_group_pos)
263         {
264           // Set the tuplet start as necessary
265           update_tuplet (infos_[i].start_moment_, infos_[i].factor_, &tuplet_start_moment);
266           Moment dt = infos_[i].start_moment_ - group_pos;
267           Rational tuplet = infos_[i].factor_;
268           Moment tuplet_moment (tuplet);
269           Moment tuplet_dt = infos_[i].start_moment_ - tuplet_start_moment;
270           tuplet_number = tuplet.den ();
271           // set the beat end (if not in a tuplet) and increment the next beat
272           if (tuplet_number == 1 && infos_[i].start_moment_ == next_beat_pos)
273             {
274               infos_[i].rhythmic_importance_ = -1;
275               next_beat_pos += options.base_moment_;
276             }
277           // The rhythmic importance of a stem between beats depends on its fraction
278           // of a beat: those stems with a lower denominator are deemed more
279           // important.  For tuplets, we need to make sure that we use
280           // the fraction of the tuplet, instead of the fraction of
281           // a beat.
282           Moment ratio = (tuplet_number == 1)
283                            ? dt / options.base_moment_
284                            : tuplet_dt / Moment (1, 8)  / tuplet_moment;
285           if (infos_[i].rhythmic_importance_ >= 0)
286             infos_[i].rhythmic_importance_ = (int) ratio.den ();
287
288           i++;
289         }
290
291       if (i < infos_.size () && infos_[i].start_moment_ == next_beat_pos)
292         {
293           if (tuplet_number == 1)
294             infos_[i].rhythmic_importance_ = -1;
295           next_beat_pos += options.base_moment_;
296           if (infos_[i].start_moment_ == next_group_pos)
297             infos_[i].rhythmic_importance_ = -2;
298         }
299     }
300 }
301
302 /*
303   Invisible stems should be treated as though they have the same number of
304   beams as their least-beamed neighbour. Here we go through the stems and
305   modify the invisible stems to satisfy this requirement.
306 */
307 void
308 Beaming_pattern::unbeam_invisible_stems ()
309 {
310   for (vsize i = 1; i < infos_.size (); i++)
311     if (infos_[i].invisible_)
312       {
313         int b = min (infos_[i].count (LEFT), infos_[i - 1].count (LEFT));
314         infos_[i].beam_count_drul_[LEFT] = b;
315         infos_[i].beam_count_drul_[RIGHT] = b;
316       }
317
318   if (infos_.size () > 1)
319     for (vsize i = infos_.size () - 1; i--;)
320       if (infos_[i].invisible_)
321         {
322           int b = min (infos_[i].count (LEFT), infos_[i + 1].count (LEFT));
323           infos_[i].beam_count_drul_[LEFT] = b;
324           infos_[i].beam_count_drul_[RIGHT] = b;
325         }
326 }
327
328 void
329 Beaming_pattern::add_stem (Moment m, int b, bool invisible, Rational factor)
330 {
331   infos_.push_back (Beam_rhythmic_element (m, b, invisible, factor));
332 }
333
334 Beaming_pattern::Beaming_pattern ()
335 {
336 }
337
338 int
339 Beaming_pattern::beamlet_count (int i, Direction d) const
340 {
341   return infos_.at (i).beam_count_drul_[d];
342 }
343
344 Moment
345 Beaming_pattern::start_moment (int i) const
346 {
347   return infos_.at (i).start_moment_;
348 }
349
350 Moment
351 Beaming_pattern::end_moment (int i) const
352 {
353   Duration *dur = new Duration (2 + max (beamlet_count (i, LEFT),
354                                          beamlet_count (i, RIGHT)),
355                                 0);
356
357   return infos_.at (i).start_moment_ + dur->get_length ();
358 }
359
360 bool
361 Beaming_pattern::invisibility (int i) const
362 {
363   return infos_.at (i).invisible_;
364 }
365
366 Rational
367 Beaming_pattern::factor (int i) const
368 {
369   return infos_.at (i).factor_;
370 }
371
372 /*
373     Split a beaming pattern at index i and return a new
374     Beaming_pattern containing the removed elements
375 */
376 Beaming_pattern *
377 Beaming_pattern::split_pattern (int i)
378 {
379   Beaming_pattern *new_pattern = 0;
380   int count;
381
382   new_pattern = new Beaming_pattern ();
383   for (vsize j = i + 1; j < infos_.size (); j++)
384     {
385       count = max (beamlet_count (j, LEFT), beamlet_count (j, RIGHT));
386       new_pattern->add_stem (start_moment (j),
387                              count,
388                              invisibility (j),
389                              factor (j));
390     }
391   for (vsize j = i + 1; j < infos_.size ();)
392     infos_.pop_back ();
393   return (new_pattern);
394 }
395
396 void
397 Beaming_options::from_context (Context *context)
398 {
399   grouping_ = context->get_property ("beatStructure");
400   subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
401   strict_beat_beaming_ = to_boolean (context->get_property ("strictBeatBeaming"));
402   base_moment_ = robust_scm2moment (context->get_property ("baseMoment"),
403                                     Moment (1, 4));
404   measure_length_ = robust_scm2moment (context->get_property ("measureLength"),
405                                        Moment (4, 4));
406 }
407
408 Beaming_options::Beaming_options ()
409 {
410   grouping_ = SCM_EOL;
411   subdivide_beams_ = false;
412   strict_beat_beaming_ = false;
413 }