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