void process_acknowledged ();
private:
- bool test_moment (Direction, Moment);
- void consider_begin (Moment);
- void consider_end (Moment);
+ bool test_moment (Direction, Moment, Moment);
+ void consider_begin (Moment, Moment);
+ void consider_end (Moment, Moment);
Spanner *create_beam ();
void begin_beam ();
void end_beam ();
void junk_beam ();
bool is_same_grace_state (Grob *e);
+ void recheck_beam ();
void typeset_beam ();
+ vector<Item*> *remove_end_stems (vsize);
Stream_event *forbid_;
/*
- shortest_mom is the shortest note in the beam.
+ shortest_mom_ is the shortest note in the beam.
*/
Moment shortest_mom_;
Spanner *finished_beam_;
Beaming_options beaming_options_;
Beaming_options finished_beaming_options_;
-
-
+
+
void check_bar_property ();
};
if (scm_is_string (get_property ("whichBar"))
&& beam_start_moment_ < now)
{
- consider_end (shortest_mom_);
+ consider_end (measure_position (context ()), shortest_mom_);
junk_beam ();
}
}
void
Auto_beam_engraver::process_music ()
{
+ Moment now = now_mom ();
/*
don't beam over skips
*/
if (stems_)
{
- Moment now = now_mom ();
if (extend_mom_ < now)
end_beam ();
}
if (scm_is_string (get_property ("whichBar")))
{
- consider_end (shortest_mom_);
+ consider_end (measure_position (context ()), shortest_mom_);
junk_beam ();
}
if (forbid_)
{
- consider_end (shortest_mom_);
+ consider_end (measure_position (context ()), shortest_mom_);
junk_beam ();
}
}
}
bool
-Auto_beam_engraver::test_moment (Direction dir, Moment test)
+Auto_beam_engraver::test_moment (Direction dir, Moment test_mom, Moment dur)
{
- return scm_call_3 (get_property ("autoBeamCheck"),
+ return scm_call_4 (get_property ("autoBeamCheck"),
context ()->self_scm (),
scm_from_int (dir),
- test.smobbed_copy ())
+ test_mom.smobbed_copy(),
+ dur.smobbed_copy ())
!= SCM_BOOL_F;
}
void
-Auto_beam_engraver::consider_begin (Moment test_mom)
+Auto_beam_engraver::consider_begin (Moment test_mom, Moment dur)
{
bool on = to_boolean (get_property ("autoBeaming"));
if (!stems_ && on
&& !forbid_)
{
- bool b = test_moment (START, test_mom);
+ bool b = test_moment (START, test_mom, dur);
if (b)
begin_beam ();
}
}
void
-Auto_beam_engraver::consider_end (Moment test_mom)
+Auto_beam_engraver::consider_end (Moment test_mom, Moment dur)
{
if (stems_)
{
/* Allow already started autobeam to end:
don't check for autoBeaming */
- bool b = test_moment (STOP, test_mom);
+ bool b = test_moment (STOP, test_mom, dur);
if (b)
end_beam ();
}
else
{
finished_beam_ = create_beam ();
-
+
if (finished_beam_)
{
announce_end_grob (finished_beam_, SCM_EOL);
{
if (!finished_beam_->get_bound (RIGHT))
finished_beam_->set_bound (RIGHT, finished_beam_->get_bound (LEFT));
-
+
finished_grouping_->beamify (finished_beaming_options_);
Beam::set_beaming (finished_beam_, finished_grouping_);
finished_beam_ = 0;
if (bool (beam_start_location_.grace_part_) != bool (now.grace_part_))
return;
- Moment dur = unsmob_duration (ev->get_property ("duration"))->get_length ();
-
- consider_end (dur);
- consider_begin (dur);
+ Moment ev_dur = unsmob_duration (ev->get_property ("duration"))->get_length ();
+ Moment dur = Rational (1, ev_dur.den ());
+ Moment measure_now = measure_position (context ());
+ bool recheck_needed = 0;
if (dur < shortest_mom_)
+ {
+ /* new shortest moment, so store it and set recheck_needed */
shortest_mom_ = dur;
+ recheck_needed = 1;
+ }
+
+ /* end should be based on shortest_mom_, begin should be
+ based on current duration */
+ consider_end (measure_now, shortest_mom_);
+ consider_begin (measure_now, dur);
if (!stems_)
return;
stems_->push_back (stem);
last_add_mom_ = now;
extend_mom_ = max (extend_mom_, now) + get_event_length (ev, now);
+ if (recheck_needed) recheck_beam ();
+}
+
+void
+Auto_beam_engraver::recheck_beam ()
+{
+ /*
+ Recheck the beam after the shortest duration has changed
+ If shorter duration has created a new break, typeset the
+ first part of the beam and reset the current beam to just
+ the last part of the beam
+ */
+ Beaming_pattern *new_grouping_ = 0;
+ vector<Item*> *new_stems_ = 0;
+ Moment temporary_shortest_mom;
+ SCM temporary_beam_settings;
+
+ bool found_end;
+
+
+ for (vsize i = 0; i < stems_->size () - 1; )
+ {
+ found_end = test_moment (STOP,
+ grouping_->end_moment (i),
+ shortest_mom_);
+ if (!found_end)
+ i++;
+ else
+ {
+ /*
+ Save the current beam settings and shortest_mom_
+ Necessary because end_beam destroys them
+ */
+ temporary_shortest_mom = shortest_mom_;
+ temporary_beam_settings = beam_settings_;
+
+ /* Eliminate (and save) the items no longer part of the first beam */
+
+ new_grouping_ = grouping_->split_pattern (i);
+ new_stems_ = remove_end_stems (i);
+
+ end_beam ();
+ typeset_beam ();
+
+ /* now recreate the unbeamed data structures */
+ stems_ = new_stems_;
+ grouping_ = new_grouping_;
+ shortest_mom_ = temporary_shortest_mom;
+ beam_settings_ = temporary_beam_settings;
+
+ i = 0;
+ }
+
+ }
+
+}
+
+/*
+ Remove all stems with an index greater than split_index
+ from stems_, and return a vector containing all of the
+ removed stems
+*/
+vector <Item*> *
+Auto_beam_engraver::remove_end_stems (vsize split_index)
+{
+ vector <Item*> *removed_stems = 0;
+ removed_stems = new vector <Item*>;
+
+ for (vsize j=split_index + 1; j < stems_->size (); j++)
+ removed_stems->push_back ((*stems_).at (j));
+ for (vsize j=split_index + 1; j < stems_->size (); )
+ stems_->pop_back ();
+ return (removed_stems);
}
void
Auto_beam_engraver::process_acknowledged ()
{
- if (extend_mom_ > now_mom ())
+ Moment now = now_mom();
+ if (extend_mom_ > now)
return;
if (!process_acknowledged_count_)
{
- consider_end (shortest_mom_);
- consider_begin (shortest_mom_);
+ Moment measure_now = measure_position (context ());
+ consider_end (measure_now, shortest_mom_);
+ consider_begin (measure_now, shortest_mom_);
}
else if (process_acknowledged_count_ > 1)
{
if (stems_)
{
- Moment now = now_mom ();
if ((extend_mom_ < now)
|| ((extend_mom_ == now) && (last_add_mom_ != now)))
end_beam ();
"beamSettings "
"beatLength "
"subdivideBeams ",
-
+
/* write */
""
);
Real line = Staff_symbol_referencer::line_thickness (me);
Real beam_thickness = get_beam_thickness (me);
Real fract = robust_scm2double (me->get_property ("length-fraction"), 1.0);
-
+
Real beam_translation = beam_count < 4
? (2 * staff_space + line - beam_thickness) / 2.0
: (3 * staff_space + line - beam_thickness) / 3.0;
Beam::calc_normal_stems (SCM smob)
{
Grob *me = unsmob_grob (smob);
-
+
extract_grob_set (me, "stems", stems);
SCM val = Grob_array::make_array ();
Grob_array *ga = unsmob_grob_array (val);
for (vsize i = 0; i < stems.size (); i++)
if (Stem::is_normal_stem (stems[i]))
ga->add (stems[i]);
-
- return val;
+
+ return val;
}
MAKE_SCHEME_CALLBACK (Beam, calc_direction, 1);
return SCM_UNSPECIFIED;
}
- else
+ else
{
Grob *stem = first_normal_stem (me);
*/
if (!stem)
stem = stems[0];
-
- if (is_direction (stem->get_property_data ("direction")))
+
+ if (is_direction (stem->get_property_data ("direction")))
dir = to_dir (stem->get_property_data ("direction"));
else
dir = to_dir (stem->get_property ("default-direction"));
{
if (!dir)
dir = get_default_dir (me);
-
+
consider_auto_knees (me);
}
{
set_stem_directions (me, dir);
}
-
+
return scm_from_int (dir);
}
Beam::calc_beaming (SCM smob)
{
Grob *me = unsmob_grob (smob);
-
+
extract_grob_set (me, "stems", stems);
Slice last_int;
last_int.set_empty ();
-
+
SCM last_beaming = scm_cons (SCM_EOL, scm_list_1 (scm_from_int (0)));
Direction last_dir = CENTER;
for (vsize i = 0; i < stems.size (); i++)
else
{
/*
- FIXME: what's this for?
+ FIXME: what's this for?
*/
SCM s = scm_cdr (this_beaming);
for (; scm_is_pair (s); s = scm_cdr (s))
last_int.add_point (np);
}
}
-
+
if (scm_ilength (scm_cdr (this_beaming)) > 0)
{
last_beaming = this_beaming;
return a.rank_ < b.rank_;
}
-typedef map<int, vector<Beam_stem_segment> > Position_stem_segments_map;
+typedef map<int, vector<Beam_stem_segment> > Position_stem_segments_map;
vector<Beam_segment>
Beam::get_beam_segments (Grob *me_grob, Grob **common)
commonx = me->get_bound (RIGHT)->common_refpoint (commonx, X_AXIS);
*common = commonx;
-
+
int gap_count = robust_scm2int (me->get_property ("gap-count"), 0);
Real gap_length = robust_scm2double (me->get_property ("gap"), 0.0);
int beam_rank = scm_to_int (scm_car (s));
ranks.add_point (beam_rank);
}
-
+
for (SCM s = index_get_cell (beaming, d);
scm_is_pair (s); s = scm_cdr (s))
{
if (!scm_is_integer (scm_car (s)))
continue;
-
+
int beam_rank = scm_to_int (scm_car (s));
Beam_stem_segment seg;
seg.stem_ = stem;
seg.stem_index_ = i;
seg.dir_ = d;
seg.max_connect_ = robust_scm2int (stem->get_property ("max-beam-connect"), 1000);
-
+
Direction stem_dir = get_grob_direction (stem);
-
+
seg.gapped_
= (stem_dir * beam_rank < (stem_dir * ranks[-stem_dir] + gap_count));
stem_segments[beam_rank].push_back (seg);
bool inside_stem = (event_dir == LEFT)
? seg.stem_index_ > 0
: seg.stem_index_ + 1 < stems.size () ;
-
+
bool event = on_beam_bound
|| abs (seg.rank_ - neighbor_seg.rank_) > 1
|| (abs (vertical_count) >= seg.max_connect_
|| abs (vertical_count) >= neighbor_seg.max_connect_);
-
+
if (!event)
// Then this edge of the current segment is irrelevent because it will
// be connected with the next segment in the event_dir direction.
}
while (flip (&event_dir) != LEFT);
}
-
+
}
return segments;
}
else
{
- extract_grob_set (me, "stems", stems);
+ extract_grob_set (me, "stems", stems);
span[LEFT] = stems[0]->relative_coordinate (commonx, X_AXIS);
span[RIGHT] = stems.back ()->relative_coordinate (commonx, X_AXIS);
}
Real beam_dy = get_beam_translation (me);
Direction feather_dir = to_dir (me->get_property ("grow-direction"));
-
+
Stencil the_beam;
for (vsize i = 0; i < segments.size (); i ++)
{
{
local_slope += feather_dir * segments[i].vertical_count_ * beam_dy / span.length ();
}
-
+
Stencil b = Lookup::beam (local_slope, segments[i].horizontal_.length (), beam_thickness, blot);
b.translate_axis (segments[i].horizontal_[LEFT], X_AXIS);
-
+
b.translate_axis (local_slope
* (segments[i].horizontal_[LEFT] - span.linear_combination (feather_dir))
+ pos.linear_combination (feather_dir)
+ beam_dy * segments[i].vertical_count_, Y_AXIS);
- the_beam.add_stencil (b);
+ the_beam.add_stencil (b);
}
-
+
#if (DEBUG_BEAM_SCORING)
SCM annotation = me->get_property ("annotation");
if (!scm_is_string (annotation))
if (to_boolean (debug))
annotation = me->get_property ("quant-score");
}
-
+
if (scm_is_string (annotation))
{
- extract_grob_set (me, "stems", stems);
+ extract_grob_set (me, "stems", stems);
/*
This code prints the demerits for each beam. Perhaps this
the_beam.translate_axis (-me->relative_coordinate (commonx, X_AXIS), X_AXIS);
return the_beam.smobbed_copy ();
}
-
+
Direction
Beam::get_default_dir (Grob *me)
{
else if (extremes[UP] < -extremes[DOWN])
return UP;
}
-
+
Direction dir = CENTER;
Direction d = CENTER;
if ((d = (Direction) sign (count[UP] - count[DOWN])))
dir = d;
else
dir = to_dir (me->get_property ("neutral-direction"));
-
+
return dir;
}
}
}
-
+
MAKE_SCHEME_CALLBACK (Beam, calc_stem_shorten, 1)
SCM
Beam::calc_stem_shorten (SCM smob)
{
Grob *me = unsmob_grob (smob);
-
+
/*
shortening looks silly for x staff beams
*/
shorten *= forced_fraction;
-
+
if (shorten)
return scm_from_double (shorten);
extract_grob_set (me, "stems", stems);
if (stems.empty ())
return default_value;
-
+
Interval head_positions;
Slice multiplicity;
for (vsize i = 0; i < stems.size(); i++)
if (normal_stem_count (me) <= 1)
return posns;
-
+
SCM s = me->get_property ("damping");
Real damping = scm_to_double (s);
Real concaveness = robust_scm2double (me->get_property ("concaveness"), 0.0);
me->set_property ("least-squares-dy", scm_from_double (0));
damping = 0;
}
-
+
if (damping)
{
scale_drul (&pos, Staff_symbol_referencer::staff_space (me));
in POS for stem S. This Y position is relative to S. */
Real
Beam::calc_stem_y (Grob *me, Grob *stem, Grob **common,
- Real xl, Real xr, Direction feather_dir,
+ Real xl, Real xr, Direction feather_dir,
Drul_array<Real> pos, bool french)
{
Real beam_translation = get_beam_translation (me);
/*
feather dir = 1 , relx 0->1 : factor 0 -> 1
- feather dir = 0 , relx 0->1 : factor 1 -> 1
- feather dir = -1, relx 0->1 : factor 1 -> 0
+ feather dir = 0 , relx 0->1 : factor 1 -> 1
+ feather dir = -1, relx 0->1 : factor 1 -> 0
*/
Real feather_factor = 1;
if (feather_dir > 0)
feather_factor = relx;
else if (feather_dir < 0)
feather_factor = 1 - relx;
-
+
stem_y += feather_factor * beam_translation
* beam_multiplicity[Direction(((french) ? DOWN : UP)*stem_dir)];
Real id = me->relative_coordinate (common[Y_AXIS], Y_AXIS)
Hmm. At this time, beam position and slope are determined. Maybe,
stem directions and length should set to relative to the chord's
position of the beam. */
-MAKE_SCHEME_CALLBACK (Beam, set_stem_lengths, 1);
+MAKE_SCHEME_CALLBACK (Beam, set_stem_lengths, 1);
SCM
Beam::set_stem_lengths (SCM smob)
{
(void) me->get_property ("beaming");
SCM posns = me->get_property ("positions");
-
+
extract_grob_set (me, "stems", stems);
if (!stems.size ())
return posns;
/* I can imagine counting those boundaries as a half forced stem,
but let's count them full for now. */
Direction defdir = to_dir (s->get_property ("default-direction"));
-
+
if (abs (Stem::chord_start_y (s)) > 0.1
&& defdir
&& get_grob_direction (s) != defdir)
return scm_from_int (0);
Real offset = robust_scm2double (prev_offset, 0.0);
-
+
Grob *st = unsmob_grob (rest->get_object ("stem"));
Grob *stem = st;
if (!stem)
Drul_array<Grob*> visible_stems (first_normal_stem (beam),
last_normal_stem (beam));
extract_grob_set (beam, "stems", stems);
-
+
Grob *common = common_refpoint_of_array (stems, beam, X_AXIS);
-
+
Real x0 = visible_stems[LEFT]->relative_coordinate (common, X_AXIS);
Real dx = visible_stems[RIGHT]->relative_coordinate (common, X_AXIS) - x0;
Real slope = dy && dx ? dy / dx : 0;
*/
Interval rest_extent = rest->extent (common_y, Y_AXIS);
rest_extent.translate (offset);
-
+
Real rest_dim = rest_extent[d];
Real minimum_distance
= staff_space * (robust_scm2double (stem->get_property ("stemlet-length"), 0.0)
"Damping slope which is considered zero for purposes of"
" calculating direction penalties.\n"
"@end table\n",
-
+
/* properties */
"annotation "
"auto-knee-gap "