2 beaming-info.cc -- implement Beam_rhythmic_element, Beaming_pattern
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 #include "beaming-pattern.hh"
12 Beam_rhythmic_element::Beam_rhythmic_element ()
15 beam_count_drul_
[LEFT
] = 0;
16 beam_count_drul_
[RIGHT
] = 0;
20 Beam_rhythmic_element::Beam_rhythmic_element (Moment m
, int i
)
23 beam_count_drul_
[LEFT
] = i
;
24 beam_count_drul_
[RIGHT
] = i
;
29 Beam_rhythmic_element::de_grace ()
31 if (start_moment_
.grace_part_
)
33 start_moment_
.main_part_
=
34 start_moment_
.grace_part_
;
35 start_moment_
.grace_part_
= 0;
40 count_factor_twos (int x
)
43 while (x
&& x
% 2 == 0)
53 Beaming_pattern::best_splitpoint_index (bool *at_boundary
) const
56 for (vsize i
= 1; i
< infos_
.size (); i
++)
58 if (infos_
[i
].group_start_
== infos_
[i
].start_moment_
)
62 for (vsize i
= 1; i
< infos_
.size (); i
++)
64 if (infos_
[i
].beat_start_
== infos_
[i
].start_moment_
)
70 int min_den
= INT_MAX
;
74 for (vsize i
= 1; i
< infos_
.size (); i
++)
76 Moment dt
= infos_
[i
].start_moment_
- infos_
[i
].beat_start_
;
79 This is a kludge, for the most common case of 16th, 32nds
80 etc. What should really happen is that \times x/y should
81 locally introduce a voice-specific beat duration. (or
82 perhaps: a list of beat durations for nested tuplets.)
86 dt
/= infos_
[i
].beat_length_
;
88 if (dt
.den () < min_den
)
99 Beaming_pattern::beam_extend_count (Direction d
) const
101 if (infos_
.size () == 1)
102 return infos_
[0].beam_count_drul_
[d
];
104 Beam_rhythmic_element thisbeam
= boundary (infos_
, d
, 0);
105 Beam_rhythmic_element next
= boundary (infos_
, d
, 1);
107 return min (thisbeam
.beam_count_drul_
[-d
], next
.beam_count_drul_
[d
]);
111 Beaming_pattern::de_grace ()
113 for (vsize i
= 0; i
< infos_
.size (); i
++)
115 infos_
[i
].de_grace ();
120 Beaming_pattern::beamify (Context
*context
)
122 if (infos_
.size () <= 1)
125 if (infos_
[0].start_moment_
.grace_part_
)
128 bool subdivide_beams
= to_boolean (context
->get_property ("subdivideBeams"));
129 Moment beat_length
= robust_scm2moment (context
->get_property ("beatLength"), Moment (1, 4));
130 Moment measure_length
= robust_scm2moment (context
->get_property ("measureLength"), Moment (1, 4));
132 if (infos_
[0].start_moment_
< Moment (0))
133 for (vsize i
= 0; i
< infos_
.size(); i
++)
134 infos_
[i
].start_moment_
+= measure_length
;
136 SCM grouping
= context
->get_property ("beatGrouping");
137 Moment
measure_pos (0);
139 vector
<Moment
> group_starts
;
140 vector
<Moment
> beat_starts
;
142 while (measure_pos
<= infos_
.back().start_moment_
)
145 if (scm_is_pair (grouping
))
147 count
= scm_to_int (scm_car (grouping
));
148 grouping
= scm_cdr (grouping
);
151 group_starts
.push_back (measure_pos
);
152 for (int i
= 0; i
< count
; i
++)
154 beat_starts
.push_back (measure_pos
+ beat_length
* i
);
156 measure_pos
+= beat_length
* count
;
161 for (vsize i
= 0; i
< infos_
.size(); i
++)
163 while (j
< group_starts
.size() - 1
164 && group_starts
[j
+1] <= infos_
[i
].start_moment_
)
167 infos_
[i
].group_start_
= group_starts
[j
];
168 infos_
[i
].beat_length_
= beat_length
;
169 while (k
< beat_starts
.size() - 1
170 && beat_starts
[k
+1] <= infos_
[i
].start_moment_
)
173 infos_
[i
].beat_start_
= beat_starts
[k
];
176 beamify (subdivide_beams
);
181 Beaming_pattern::beamify (bool subdivide_beams
)
183 if (infos_
.size () <= 1)
186 Drul_array
<Beaming_pattern
> splits
;
188 bool at_boundary
= false;
189 int m
= best_splitpoint_index (&at_boundary
);
191 splits
[LEFT
].infos_
= vector
<Beam_rhythmic_element
> (infos_
.begin (),
192 infos_
.begin () + m
);
193 splits
[RIGHT
].infos_
= vector
<Beam_rhythmic_element
> (infos_
.begin () + m
,
200 splits
[d
].beamify (subdivide_beams
);
202 while (flip (&d
) != LEFT
);
204 int middle_beams
= ((at_boundary
&& subdivide_beams
)
206 : min (splits
[RIGHT
].beam_extend_count (LEFT
),
207 splits
[LEFT
].beam_extend_count (RIGHT
)));
211 if (splits
[d
].infos_
.size () != 1)
212 boundary (splits
[d
].infos_
, -d
, 0).beam_count_drul_
[-d
] = middle_beams
;
214 while (flip (&d
) != LEFT
);
216 infos_
= splits
[LEFT
].infos_
;
217 infos_
.insert (infos_
.end (),
218 splits
[RIGHT
].infos_
.begin (),
219 splits
[RIGHT
].infos_
.end ());
224 Beaming_pattern::add_stem (Moment m
, int b
)
226 infos_
.push_back (Beam_rhythmic_element (m
, b
));
229 Beaming_pattern::Beaming_pattern ()
234 Beaming_pattern::beamlet_count (int i
, Direction d
) const
236 return infos_
.at (i
).beam_count_drul_
[d
];