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