]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-pattern.cc
Fix 638: Fix autobeaming in 4 4 time.
[lilypond.git] / lily / beaming-pattern.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1999--2009 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 "beam-settings.hh"
22 #include "beaming-pattern.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
44 }
45
46 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv)
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 }
54
55 void
56 Beam_rhythmic_element::de_grace ()
57 {
58   if (start_moment_.grace_part_)
59     {
60       start_moment_.main_part_ = start_moment_.grace_part_;
61       start_moment_.grace_part_ = 0;
62     }
63 }
64
65 int
66 Beam_rhythmic_element::count (Direction d) const
67 {
68   return beam_count_drul_[d];
69 }
70
71 /*
72   Finds the appropriate direction for the flags at the given index that
73   hang below the neighbouring flags. If
74   the stem has no more flags than either of its neighbours, this returns
75   CENTER.
76 */
77 Direction
78 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
79 {
80   // The extremal stems shouldn't be messed with, so it's appropriate to
81   // return CENTER here also.
82   if (i == 0 || i == infos_.size () - 1)
83     return CENTER;
84
85   int count = infos_[i].count (LEFT); // Both directions should still be the same
86   int left_count = infos_[i-1].count (RIGHT);
87   int right_count = infos_[i+1].count (LEFT);
88
89   // If we are told to subdivide beams and we are next to a beat, point the
90   // beamlet away from the beat.
91   if (options.subdivide_beams_)
92     {
93       if (infos_[i].rhythmic_importance_ < 0)
94         return RIGHT;
95       else if (infos_[i+1].rhythmic_importance_ < 0)
96         return LEFT;
97     }
98
99   if (count <= left_count && count <= right_count)
100     return CENTER;
101
102   // Try to avoid sticking-out flags as much as possible by pointing my flags
103   // at the neighbour with the most flags.
104   else if (right_count > left_count)
105     return RIGHT;
106   else if (left_count > right_count)
107     return LEFT;
108
109   // If all else fails, point the beamlet away from the important moment.
110   return (infos_[i].rhythmic_importance_ <= infos_[i+1].rhythmic_importance_) ? RIGHT : LEFT;
111 }
112
113 void
114 Beaming_pattern::de_grace ()
115 {
116   for (vsize i = 0; i < infos_.size (); i ++)
117     {
118       infos_[i].de_grace ();
119     }
120 }
121
122 void
123 Beaming_pattern::beamify (Beaming_options const &options)
124 {
125   unbeam_invisible_stems ();
126
127   if (infos_.size () <= 1)
128     return;
129
130   if (infos_[0].start_moment_.grace_part_)
131     de_grace ();
132
133   if (infos_[0].start_moment_ < Moment (0))
134     for (vsize i = 0; i < infos_.size (); i++)
135       infos_[i].start_moment_ += options.measure_length_;
136
137   find_rhythmic_importance (options);
138
139   for (vsize i = 1; i < infos_.size () - 1; i++)
140     {
141       Direction non_flag_dir = other_dir (flag_direction (options, i));
142       if (non_flag_dir)
143         {
144           int importance = (non_flag_dir == LEFT)
145             ? infos_[i].rhythmic_importance_ : infos_[i+1].rhythmic_importance_;
146           int count = (importance < 0 && options.subdivide_beams_)
147             ? 1 : min (infos_[i].count (non_flag_dir),
148                        infos_[i+non_flag_dir].count (-non_flag_dir));
149
150           infos_[i].beam_count_drul_[non_flag_dir] = count;
151         }
152     }
153 }
154
155 void
156 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
157 {
158   Moment measure_pos (0);
159   SCM grouping = options.grouping_;
160   vsize i = 0;
161
162   // Mark the importance of stems that start at a beat or a beat group.
163   while (i < infos_.size ())
164     {
165       // If a beat grouping is not specified, default to 2 beats per group.
166       int count = 2;
167       if (scm_is_pair (grouping))
168         {
169           count = scm_to_int (scm_car (grouping));
170           grouping = scm_cdr (grouping);
171         }
172
173       // Mark the start of this beat group
174       if (infos_[i].start_moment_ == measure_pos)
175         infos_[i].rhythmic_importance_ = -2;
176
177       // Mark the start of each beat up to the end of this beat group.
178       for (int beat = 1; beat <= count; beat++)
179         {
180           Moment next_measure_pos = measure_pos + options.beat_length_;
181
182           while (i < infos_.size () && infos_[i].start_moment_ < next_measure_pos)
183             {
184               Moment dt = infos_[i].start_moment_ - measure_pos;
185
186               // The rhythmic importance of a stem between beats depends on its fraction
187               // of a beat: those stems with a lower denominator are deemed more
188               // important.
189               // FIXME: This is not the right way to do things for tuplets. For example,
190               // in an 8th-note triplet with a quarter-note beat, 1/3 of a beat should be
191               // more important than 1/2.
192               if (infos_[i].rhythmic_importance_ >= 0)
193                 infos_[i].rhythmic_importance_ = (dt / options.beat_length_).den ();
194
195               i++;
196             }
197
198           measure_pos = next_measure_pos;
199           if (i < infos_.size () && infos_[i].start_moment_ == measure_pos)
200             infos_[i].rhythmic_importance_ = -1;
201         }
202     }
203 }
204
205
206 /*
207   Invisible stems should be treated as though they have the same number of
208   beams as their least-beamed neighbour. Here we go through the stems and
209   modify the invisible stems to satisfy this requirement.
210 */
211 void
212 Beaming_pattern::unbeam_invisible_stems ()
213 {
214   for (vsize i = 1; i < infos_.size (); i++)
215     if (infos_[i].invisible_)
216       {
217         int b = min (infos_[i].count (LEFT), infos_[i-1].count (LEFT));
218         infos_[i].beam_count_drul_[LEFT] = b;
219         infos_[i].beam_count_drul_[RIGHT] = b;
220       }
221
222   for (vsize i = infos_.size (); i--;)
223     if (infos_[i].invisible_)
224       {
225         int b = min (infos_[i].count (LEFT), infos_[i+1].count (LEFT));
226         infos_[i].beam_count_drul_[LEFT] = b;
227         infos_[i].beam_count_drul_[RIGHT] = b;
228       }
229 }
230
231
232 void
233 Beaming_pattern::add_stem (Moment m, int b, bool invisible)
234 {
235   infos_.push_back (Beam_rhythmic_element (m, b, invisible));
236 }
237
238 Beaming_pattern::Beaming_pattern ()
239 {
240 }
241
242 int
243 Beaming_pattern::beamlet_count (int i, Direction d) const
244 {
245   return infos_.at (i).beam_count_drul_[d];
246 }
247
248 Moment
249 Beaming_pattern::start_moment (int i) const
250 {
251   return infos_.at (i).start_moment_;
252 }
253
254 Moment
255 Beaming_pattern::end_moment (int i) const
256 {
257   Duration *dur = new Duration (2 + max (beamlet_count (i, LEFT),
258                                         beamlet_count (i, RIGHT)),
259                                0);
260
261   return infos_.at (i).start_moment_ + dur->get_length();
262 }
263
264 bool
265 Beaming_pattern::invisibility (int i) const
266 {
267   return infos_.at (i).invisible_;
268 }
269
270 /*
271     Split a beamin pattern at index i and return a new
272     Beaming_pattern containing the removed elements
273 */
274 Beaming_pattern *
275 Beaming_pattern::split_pattern (int i)
276 {
277   Beaming_pattern* new_pattern=0;
278   int count;
279
280   new_pattern = new Beaming_pattern ();
281   for (vsize j=i+1; j<infos_.size (); j++)
282     {
283       count = max(beamlet_count (j, LEFT), beamlet_count(j, RIGHT));
284       new_pattern->add_stem (start_moment (j),
285                              count,
286                              invisibility (j));
287     }
288   for (vsize j=i+1; j<infos_.size (); )
289     infos_.pop_back ();
290   return (new_pattern);
291 }
292
293 void
294 Beaming_options::from_context (Context *context)
295 {
296   grouping_ = ly_beat_grouping (context->self_scm ());
297   subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
298   beat_length_ = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4));
299   measure_length_ = robust_scm2moment (context->get_property ("measureLength"), Moment (4, 4));
300 }
301
302 Beaming_options::Beaming_options ()
303 {
304   grouping_ = SCM_EOL;
305   subdivide_beams_ = false;
306 }