2 beaming-info.cc -- implement Beam_rhythmic_element, Beaming_pattern
4 A Beaming_pattern object takes a set of stems at given moments and calculates
5 the pattern of their beam. That is, it works out, for each stem, how many
6 beams should be connected to the right and left sides of that stem. In
7 calculating this, Beaming_pattern takes into account
8 - the rhythmic position of the stems
9 - the options that are defined in Beaming_options
11 source file of the GNU LilyPond music typesetter
13 (c) 1999--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
16 #include "beaming-pattern.hh"
20 Represents a stem belonging to a beam. Sometimes (for example, if the stem
21 belongs to a rest and stemlets aren't used) the stem will be invisible.
23 The rhythmic_importance_ of an element tells us the significance of the
24 moment at which this element occurs. For example, an element that occurs at
25 a beat is more significant than one that doesn't. Smaller number are
26 more important. The rhythmic_importance_ is decided and filled in by
27 Beaming_pattern. A rhythmic_importance_ smaller than zero has extra
28 significance: it represents the start of a beat and therefore beams may
29 need to be subdivided.
31 Beam_rhythmic_element::Beam_rhythmic_element ()
34 rhythmic_importance_
= 0;
35 beam_count_drul_
[LEFT
] = 0;
36 beam_count_drul_
[RIGHT
] = 0;
41 Beam_rhythmic_element::Beam_rhythmic_element (Moment m
, int i
, bool inv
)
44 rhythmic_importance_
= 0;
45 beam_count_drul_
[LEFT
] = i
;
46 beam_count_drul_
[RIGHT
] = i
;
51 Beam_rhythmic_element::de_grace ()
53 if (start_moment_
.grace_part_
)
55 start_moment_
.main_part_
= start_moment_
.grace_part_
;
56 start_moment_
.grace_part_
= 0;
61 Beam_rhythmic_element::count (Direction d
) const
63 return beam_count_drul_
[d
];
67 Finds the appropriate direction for the flags at the given index that
68 hang below the neighbouring flags. If
69 the stem has no more flags than either of its neighbours, this returns
73 Beaming_pattern::flag_direction (Beaming_options
const &options
, vsize i
) const
75 // The extremal stems shouldn't be messed with, so it's appropriate to
76 // return CENTER here also.
77 if (i
== 0 || i
== infos_
.size () - 1)
80 int count
= infos_
[i
].count (LEFT
); // Both directions should still be the same
81 int left_count
= infos_
[i
-1].count (RIGHT
);
82 int right_count
= infos_
[i
+1].count (LEFT
);
84 // If we are told to subdivide beams and we are next to a beat, point the
85 // beamlet away from the beat.
86 if (options
.subdivide_beams_
)
88 if (infos_
[i
].rhythmic_importance_
< 0)
90 else if (infos_
[i
+1].rhythmic_importance_
< 0)
94 if (count
<= left_count
&& count
<= right_count
)
97 // Try to avoid sticking-out flags as much as possible by pointing my flags
98 // at the neighbour with the most flags.
99 else if (right_count
> left_count
)
101 else if (left_count
> right_count
)
104 // If all else fails, point the beamlet away from the important moment.
105 return (infos_
[i
].rhythmic_importance_
<= infos_
[i
+1].rhythmic_importance_
) ? RIGHT
: LEFT
;
109 Beaming_pattern::de_grace ()
111 for (vsize i
= 0; i
< infos_
.size (); i
++)
113 infos_
[i
].de_grace ();
118 Beaming_pattern::beamify (Beaming_options
const &options
)
120 unbeam_invisible_stems ();
122 if (infos_
.size () <= 1)
125 if (infos_
[0].start_moment_
.grace_part_
)
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_
;
132 find_rhythmic_importance (options
);
134 for (vsize i
= 1; i
< infos_
.size () - 1; i
++)
136 Direction non_flag_dir
= other_dir (flag_direction (options
, i
));
139 int importance
= (non_flag_dir
== LEFT
)
140 ? infos_
[i
].rhythmic_importance_
: infos_
[i
+1].rhythmic_importance_
;
141 int count
= (importance
< 0 && options
.subdivide_beams_
)
142 ? 1 : min (infos_
[i
].count (non_flag_dir
),
143 infos_
[i
+non_flag_dir
].count (-non_flag_dir
));
145 infos_
[i
].beam_count_drul_
[non_flag_dir
] = count
;
151 Beaming_pattern::find_rhythmic_importance (Beaming_options
const &options
)
153 Moment
measure_pos (0);
154 SCM grouping
= options
.grouping_
;
157 // Mark the importance of stems that start at a beat or a beat group.
158 while (i
< infos_
.size ())
160 // If a beat grouping is not specified, default to 2 beats per group.
162 if (scm_is_pair (grouping
))
164 count
= scm_to_int (scm_car (grouping
));
165 grouping
= scm_cdr (grouping
);
168 // Mark the start of this beat group
169 if (infos_
[i
].start_moment_
== measure_pos
)
170 infos_
[i
].rhythmic_importance_
= -2;
172 // Mark the start of each beat up to the end of this beat group.
173 for (int beat
= 1; beat
<= count
; beat
++)
175 Moment next_measure_pos
= measure_pos
+ options
.beat_length_
;
177 while (i
< infos_
.size () && infos_
[i
].start_moment_
< next_measure_pos
)
179 Moment dt
= infos_
[i
].start_moment_
- measure_pos
;
181 // The rhythmic importance of a stem between beats depends on its fraction
182 // of a beat: those stems with a lower denominator are deemed more
184 // FIXME: This is not the right way to do things for tuplets. For example,
185 // in an 8th-note triplet with a quarter-note beat, 1/3 of a beat should be
186 // more important than 1/2.
187 if (infos_
[i
].rhythmic_importance_
>= 0)
188 infos_
[i
].rhythmic_importance_
= (dt
/ options
.beat_length_
).den ();
193 measure_pos
= next_measure_pos
;
194 if (i
< infos_
.size () && infos_
[i
].start_moment_
== measure_pos
)
195 infos_
[i
].rhythmic_importance_
= -1;
202 Invisible stems should be treated as though they have the same number of
203 beams as their least-beamed neighbour. Here we go through the stems and
204 modify the invisible stems to satisfy this requirement.
207 Beaming_pattern::unbeam_invisible_stems ()
209 for (vsize i
= 1; i
< infos_
.size (); i
++)
210 if (infos_
[i
].invisible_
)
212 int b
= min (infos_
[i
].count (LEFT
), infos_
[i
-1].count (LEFT
));
213 infos_
[i
].beam_count_drul_
[LEFT
] = b
;
214 infos_
[i
].beam_count_drul_
[RIGHT
] = b
;
217 for (vsize i
= infos_
.size (); i
--;)
218 if (infos_
[i
].invisible_
)
220 int b
= min (infos_
[i
].count (LEFT
), infos_
[i
+1].count (LEFT
));
221 infos_
[i
].beam_count_drul_
[LEFT
] = b
;
222 infos_
[i
].beam_count_drul_
[RIGHT
] = b
;
228 Beaming_pattern::add_stem (Moment m
, int b
, bool invisible
)
230 infos_
.push_back (Beam_rhythmic_element (m
, b
, invisible
));
233 Beaming_pattern::Beaming_pattern ()
238 Beaming_pattern::beamlet_count (int i
, Direction d
) const
240 return infos_
.at (i
).beam_count_drul_
[d
];
244 Beaming_options::from_context (Context
*context
)
246 grouping_
= context
->get_property ("beatGrouping");
247 subdivide_beams_
= to_boolean (context
->get_property ("subdivideBeams"));
248 beat_length_
= robust_scm2moment (context
->get_property ("beatLength"), Moment (1, 4));
249 measure_length_
= robust_scm2moment (context
->get_property ("measureLength"), Moment (1, 4));
252 Beaming_options::Beaming_options ()
255 subdivide_beams_
= false;