From: Jan Nieuwenhuizen Date: Sat, 9 Jan 1999 15:50:58 +0000 (+0100) Subject: patch::: 1.1.19.jcn3: zonder haar X-Git-Tag: release/1.1.20~3 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=e937ec183de70a106e940eab118b80d1be69872b;p=lilypond.git patch::: 1.1.19.jcn3: zonder haar pl 19.jcn3 - dehairification of beam code; cleanup and bugfixes * stemlength * forced stem shorten * slope calculation * damping and correction * catch for silly beams: input/test/beam-suspect.ly pl 19.jcn2 --- Generated by janneke@gnu.org using package-diff 0.62, >From = lilypond-1.1.19.jcn2, To = lilypond-1.1.19.jcn3 usage cd lilypond-source-dir; patch -E -p1 < lilypond-1.1.19.jcn3.diff Patches do not contain automatically generated files or (urg) empty directories, i.e., you should rerun autoconf, configure and possibly make outdirs. --state 1.1.19.jcn2 1.1.19.jcn3 ++state --- diff --git a/NEWS b/NEWS index a7003e2ef9..41e92f7bb3 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,19 @@ +--- ../lilypond-1.1.19.jcn2/NEWS Fri Jan 8 18:01:10 1999 +++ b/NEWS Sat Jan 9 16:03:22 1999 +@@ -1,4 +1,12 @@ +-pl 19.jcn1 +pl 19.jcn3 + - dehairification of beam code; cleanup and bugfixes + * stemlength + * forced stem shorten + * slope calculation + * damping and correction + * catch for silly beams: input/test/beam-suspect.ly + pl 19.jcn2 + - multi-measure-rest is now spanner SkipBars=0 is broken + + pl 19.jcn1pl 19.jcn2 - multi-measure-rest is now spanner SkipBars=0 is broken pl 19.jcn1 diff --git a/VERSION b/VERSION index 80ecd75d52..04747dc655 100644 --- a/VERSION +++ b/VERSION @@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=1 PATCH_LEVEL=19 -MY_PATCH_LEVEL=jcn2 +MY_PATCH_LEVEL=jcn3 # use the above to send patches: MY_PATCH_LEVEL is always empty for a # released version. diff --git a/init/params.ly b/init/params.ly index 35ab7533d4..3f04da0af6 100644 --- a/init/params.ly +++ b/init/params.ly @@ -50,6 +50,7 @@ beam_dir_algorithm = \MAJORITY; % % some beam-stemlength settings... % +% poor man's array % beam_*1 : multiplicity < beam_multiple_break % beam_*2 : multiplicity >= beam_multiple_break % @@ -58,9 +59,16 @@ beam_minimum_stem1 = 0.75 * \interline; beam_ideal_stem1 = 1.75 * \interline; beam_minimum_stem2 = 0.75 * \interline; beam_ideal_stem2 = 1.25 * \interline; - -% beam_slope_damp_correct_factor = 2.0; -beam_slope_damp_correct_factor = 0.0; +% same here +beam_forced_multiple_break = 2.0; +beam_forced_stem_shorten1 = 0.65 * \interline; +beam_forced_stem_shorten2 = 0.50 * \interline; + +% catch suspect beam slopes, set slope to zero if +% outer stem is lengthened more than +beam_lengthened = 0.2 * \interline; +% and slope is running away steeper than +beam_steep_slope = 0.2 / 1.0; % OSU: suggested gap = ss / 5; slur_x_gap = \interline / 5.0; diff --git a/input/test/beam-damp.ly b/input/test/beam-damp.ly new file mode 100644 index 0000000000..c6f2147b9e --- /dev/null +++ b/input/test/beam-damp.ly @@ -0,0 +1,19 @@ +\score{ + \notes\relative c''{ +% \stemup +% [a16 b b c] +% [c b b a] +% \stemdown +% [c b b a] +% [a b b c] + \stemup + [g16 a b c] + [c b a g] + \stemdown + [d' c b a] + [a b c d] + } + \paper{ + linewidth=-1.; + } +} diff --git a/input/test/beam-suspect.ly b/input/test/beam-suspect.ly new file mode 100644 index 0000000000..cf41188dcc --- /dev/null +++ b/input/test/beam-suspect.ly @@ -0,0 +1,16 @@ +\score{ + \notes\relative c'{ + \stemup + [f8 a' g f] + [c8 g'16 f] + [c8 e16 d] + [a16 b c d] + [d16 c b a] + \stemdown + [c16 b a g] + [g16 a b c] + } + \paper{ + linewidth=-1.; + } +} diff --git a/input/test/wtk-huh.ly b/input/test/wtk-huh.ly new file mode 100644 index 0000000000..3d49c18a50 --- /dev/null +++ b/input/test/wtk-huh.ly @@ -0,0 +1,18 @@ +\score{ + \type Staff \notes\relative c'''{ + < \type Voice = one { + \stemup + \voiceone + [g8 a g f] + } + \type Voice=two + { + \stemdown + \voicetwo + [c8 f e d] + }> + } + \paper{ + linewidth=-1.; + } +} diff --git a/lily/beam.cc b/lily/beam.cc index 40648d8353..4cdc6e7afe 100644 --- a/lily/beam.cc +++ b/lily/beam.cc @@ -37,7 +37,6 @@ Beam::Beam () { slope_f_ = 0; - solved_slope_f_ = 0; left_y_ = 0; damping_i_ = 1; quantisation_ = NORMAL; @@ -156,18 +155,6 @@ Beam::set_default_dir () } while (flip(&d) != DOWN); -#if 0 - /* - urg? consider [b''16 a]: will get stem down! - i'll leave this 'fix' commented-out in case something breaks. - jcn - */ - do { - if (!total[d]) - count[d] = 1; - } while (flip(&d) != DOWN); -#endif - /* [Ross] states that the majority of the notes dictates the direction (and not the mean of "center distance") @@ -214,164 +201,154 @@ Beam::set_default_dir () */ void -Beam::solve_slope (Array& sinfo) +Beam::solve_slope () { /* should use minimum energy formulation (cf linespacing) */ - assert (sinfo.size () > 1); + assert (sinfo_.size () > 1); DOUT << "Beam::solve_slope: \n"; - Real staffline_f = paper ()->rule_thickness (); - Real epsilon_f = staffline_f / 8; - - Real leftx = sinfo[0].x_; Least_squares l; - for (int i=0; i < sinfo.size (); i++) + for (int i=0; i < sinfo_.size (); i++) { - sinfo[i].x_ -= leftx; - l.input.push (Offset (sinfo[i].x_, sinfo[i].idealy_f_)); + l.input.push (Offset (sinfo_[i].x_, sinfo_[i].idealy_f_)); } - - // l.input[0].y () += left_y_; - l.input[0].y () += left_y_ / 2; l.minimise (slope_f_, left_y_); - - solved_slope_f_ = dir_ * slope_f_; - - /* - This neat trick is by Werner Lemberg, damped = tanh (slope_f_) corresponds - with some tables in [Wanske] - */ - if (damping_i_) - slope_f_ = 0.6 * tanh (slope_f_) / damping_i_; - - /* - [TODO] - think - - dropping lq for stemlengths solves [d d d] [d g d] "bug..." - - but may be a bit too crude, and result in lots of - too high beams... - - perhaps only if slope = 0 ? - */ - - if (abs (slope_f_) < epsilon_f) - left_y_ = (sinfo[0].idealy_f_ + sinfo.top ().idealy_f_) / 2; - else - /* - symmetrical, but results often in having stemlength = minimal - - left_y_ = sinfo[0].dir_ == dir_ ? sinfo[0].miny_f_ : sinfo[0].maxy_f_; - - what about - */ - { - Real dx = stems_.top ()->hpos_f () - stems_[0]->hpos_f (); - if (sinfo[0].dir_ == sinfo.top ().dir_) - left_y_ = sinfo[0].idealy_f_ >? sinfo.top ().idealy_f_ - slope_f_ * dx; - // knee - else - left_y_ = sinfo[0].idealy_f_; - } } Real -Beam::check_stemlengths_f (Array& sinfo) +Beam::check_stemlengths_f (bool set_b) { - /* - find shortest stem and adjust left_y accordingly - */ - Real dy = 0.0; - for (int i=0; i < sinfo.size (); i++) + Real interbeam_f = paper ()->interbeam_f (multiple_i_); + Real internote_f = paper ()->internote_f (); + Real beam_f = paper ()->beam_thickness_f (); + Real staffline_f = paper ()->rule_thickness (); + Real epsilon_f = staffline_f / 8; + Real dy_f = 0.0; + for (int i=0; i < sinfo_.size (); i++) { - Real y = sinfo[i].x_ * slope_f_ + left_y_; - Real my = sinfo[i].miny_f_; - - if (my - y > dy) - dy = my -y; + Real y = sinfo_[i].x_ * slope_f_ + left_y_; + // correct for knee + if (dir_ != sinfo_[i].dir_) + y -= dir_ * (beam_f / 2 + + (sinfo_[i].mult_i_ - 1) * interbeam_f) / internote_f; + + if (set_b) + sinfo_[i].stem_l_->set_stemend (y); + + y *= dir_; + if (y > sinfo_[i].maxy_f_) + dy_f = dy_f ? sinfo_[i].miny_f_ - y; + } } - return dy; + return dy_f; } void -Beam::calculate_slope () +Beam::set_steminfo () { - Real interline_f = paper ()->interline_f (); - Real staffline_f = paper ()->rule_thickness (); - Real epsilon_f = staffline_f / 8; - assert (multiple_i_); - Array sinfo; + int total_count_i = 0; + int forced_count_i = 0; for (int i=0; i < stems_.size (); i++) { Stem *s = stems_[i]; - s->mult_i_ = multiple_i_; s->set_default_extents (); + if (s->invisible_b ()) + continue; + if (((int)s->chord_start_f ()) && (s->dir_ != s->get_default_dir ())) + forced_count_i++; + total_count_i++; + } + + Real break_i = (int)rint (paper ()->get_var ("beam_forced_multiple_break")); + Real shorten_f; + if (multiple_i_ < break_i) + shorten_f = paper ()->get_var ("beam_forced_stem_shorten1"); + else + shorten_f = paper ()->get_var ("beam_forced_stem_shorten2"); + + Real internote_f = paper ()->internote_f (); + Real leftx = 0; + for (int i=0; i < stems_.size (); i++) + { + Stem *s = stems_[i]; if (s->invisible_b ()) continue; Stem_info info (s); - sinfo.push (info); + if (leftx == 0) + leftx = info.x_; + info.x_ -= leftx; + if (info.dir_ == dir_) + { + if (forced_count_i == total_count_i) + info.idealy_f_ -= shorten_f / internote_f; + else if (forced_count_i > total_count_i / 2) + info.idealy_f_ -= shorten_f / 2 / internote_f; + } + sinfo_.push (info); } +} - if (! sinfo.size ()) +void +Beam::calculate_slope () +{ + set_steminfo (); + if (!sinfo_.size ()) slope_f_ = left_y_ = 0; - else if (sinfo.size () == 1) + else if (sinfo_[0].idealy_f_ == sinfo_.top ().idealy_f_) { slope_f_ = 0; - left_y_ = sinfo[0].idealy_f_; + left_y_ = sinfo_[0].idealy_f_; + left_y_ *= dir_; } else { - Real y; - Real s; - Array local_sinfo; - local_sinfo = sinfo; - for (int i = 0; i < 5; i++) - { - y = left_y_; - solve_slope (sinfo); - Real dy = check_stemlengths_f (sinfo); - left_y_ += dy; - - // only consider recalculation if long stem adjustments - if (!i && (left_y_ - sinfo[0].idealy_f_ < 0.5 * interline_f)) - break; - - if (!i) - s = slope_f_; - // never allow slope to tilt the other way - else if (sign (slope_f_) != sign (s)) - { - left_y_ = 0; - slope_f_ = 0; - sinfo = local_sinfo; - Real dy = check_stemlengths_f (sinfo); - left_y_ += dy; - break; - } - // or become steeper - else if (abs (slope_f_) > abs (s)) - { - slope_f_ = s; - sinfo = local_sinfo; - Real dy = check_stemlengths_f (sinfo); - left_y_ += dy; - break; - } - if (abs (dy) < epsilon_f) - break; + solve_slope (); + Real solved_slope_f = slope_f_; + + /* + steep slope running against lengthened stem is suspect + */ + Real dx_f = stems_.top ()->hpos_f () - stems_[0]->hpos_f (); + + // urg, these y internote-y-dimensions + Real internote_f = paper ()->internote_f (); + Real lengthened = paper ()->get_var ("beam_lengthened") / internote_f; + Real steep = paper ()->get_var ("beam_steep_slope") / internote_f; + if (((left_y_ - sinfo_[0].idealy_f_ > lengthened) + && (slope_f_ > steep)) + || ((left_y_ + slope_f_ * dx_f - sinfo_.top ().idealy_f_ > lengthened) + && (slope_f_ < -steep))) + { + slope_f_ = 0; } - } - left_y_ *= dir_; - slope_f_ *= dir_; + /* + This neat trick is by Werner Lemberg, + damped = tanh (slope_f_) + corresponds with some tables in [Wanske] + */ + if (damping_i_) + slope_f_ = 0.6 * tanh (slope_f_) / damping_i_; + + quantise_dy (); + + Real damped_slope_dy_f = (solved_slope_f - slope_f_) * dx_f / 2; + left_y_ += damped_slope_dy_f; - quantise_dy (); + left_y_ *= dir_; + slope_f_ *= dir_; + } } void @@ -505,7 +482,7 @@ Beam::quantise_left_y (bool extend_b) if (test_pos == 0) { allowed_position.push (hang); - cout << "hang" << hang << endl; + cout << "hang" << hang << "\n"; } else if (test_pos==1) { @@ -524,13 +501,6 @@ Beam::quantise_left_y (bool extend_b) } } -#if 0 - // this currently never happens - Real q = (dy_f / interline_f - dy_i) * interline_f; - if ((quantisation_ < NORMAL) && (q < interline_f / 3 - beam_f / 2)) - allowed_position.push (inter); -#endif - Interval iv = quantise_iv (allowed_position, interline_f, dy_f); Real quanty_f = dy_f - iv.min () <= iv.max () - dy_f ? iv.min () : iv.max (); @@ -545,88 +515,19 @@ void Beam::set_stemlens () { Real staffline_f = paper ()->rule_thickness (); - Real interbeam_f = paper ()->interbeam_f (multiple_i_); - Real internote_f = paper ()->internote_f (); - Real beam_f = paper ()->beam_thickness_f (); - // enge floots Real epsilon_f = staffline_f / 8; - /* - - Damped and quantised slopes, esp. in monotone scales such as - - [c d e f g a b c] - - will soon produce the minimal stem-length for one of the extreme - stems, which is wrong (and ugly). The minimum stemlength should - be kept rather small, in order to handle extreme beaming, such as - - [c c' 'c] %assuming no knee - - correctly. - To avoid these short stems for normal cases, we'll correct for - the loss in slope, if necessary. - - [TODO] - ugh, another hack. who's next? - Writing this all down, i realise (at last) that the Right Thing to - do is to assign uglyness to slope and stem-lengths and then minimise - the total uglyness of a beam. - Steep slopes are ugly, shortened stems are ugly, lengthened stems - are ugly. - How to do this? - - */ - - Real dx_f = stems_.top ()->hpos_f () - stems_[0]->hpos_f (); - Real damp_correct_f = paper ()->get_var ("beam_slope_damp_correct_factor"); - Real damped_slope_dy_f = (solved_slope_f_ - slope_f_) * dx_f - * sign (slope_f_); - damped_slope_dy_f *= damp_correct_f; - if (damped_slope_dy_f <= epsilon_f) - damped_slope_dy_f = 0; - DOUT << "Beam::set_stemlens: \n"; - Real x0 = stems_[0]->hpos_f (); - Real dy_f = 0; - // urg - for (int jj = 0; jj < 10; jj++) + Real dy_f = check_stemlengths_f (false); + for (int i = 0; i < 2; i++) { left_y_ += dy_f * dir_; quantise_left_y (dy_f); - dy_f = 0; - for (int i=0; i < stems_.size (); i++) - { - Stem *s = stems_[i]; - if (s->transparent_b_) - continue; - - Real x = s->hpos_f () - x0; - // urg move this to stem-info - Real sy = left_y_ + slope_f_ * x; - if (dir_ != s->dir_) - sy -= dir_ * (beam_f / 2 - + (s->mult_i_ - 1) * interbeam_f) / internote_f; - s->set_stemend (sy); - Real y = s->stem_end_f () * dir_; - Stem_info info (s); - if (y > info.maxy_f_) - dy_f = dy_f ? info.miny_f_ - y; - } - } - if (damped_slope_dy_f && (dy_f >= 0)) - dy_f += damped_slope_dy_f; - damped_slope_dy_f = 0; + dy_f = check_stemlengths_f (true); if (abs (dy_f) <= epsilon_f) { - DOUT << "Beam::set_stemlens: " << jj << " iterations\n"; + DOUT << "Beam::set_stemlens: " << i << " iterations\n"; break; } } diff --git a/lily/include/beam.hh b/lily/include/beam.hh index 5c42a6ba06..fa26038d08 100644 --- a/lily/include/beam.hh +++ b/lily/include/beam.hh @@ -40,7 +40,7 @@ public: /// maximum number of beams (for opening-up of beam-spacing) int multiple_i_; - + Array sinfo_; Beam(); void add_stem (Stem*); @@ -53,6 +53,7 @@ protected: virtual Interval do_width () const; Offset center () const; void set_default_dir (); + void set_steminfo (); virtual void do_pre_processing (); virtual void do_post_processing (); virtual void do_substitute_dependent (Score_element*, Score_element*); @@ -62,8 +63,8 @@ protected: virtual void quantise_left_y (bool extend_b); virtual Molecule stem_beams (Stem *here, Stem *next, Stem *prev) const; virtual void calculate_slope (); - virtual Real check_stemlengths_f (Array& sinfo); - virtual void solve_slope (Array& sinfo); + virtual Real check_stemlengths_f (bool set_b); + virtual void solve_slope (); virtual void quantise_dy (); virtual Molecule*do_brew_molecule_p () const; }; diff --git a/lily/include/stem-info.hh b/lily/include/stem-info.hh index bff7cfbdb3..695a2c88fc 100644 --- a/lily/include/stem-info.hh +++ b/lily/include/stem-info.hh @@ -20,9 +20,10 @@ struct Stem_info { Real miny_f_; Real maxy_f_; int mult_i_; + Stem* stem_l_; Stem_info (); - Stem_info (Stem const *); + Stem_info (Stem *); }; #endif // STEM_INFO_HH diff --git a/lily/stem-info.cc b/lily/stem-info.cc index 42374eb12b..e4504b783e 100644 --- a/lily/stem-info.cc +++ b/lily/stem-info.cc @@ -20,12 +20,13 @@ Stem_info::Stem_info () { } -Stem_info::Stem_info (Stem const *s) +Stem_info::Stem_info (Stem*s) { - x_ = s->hpos_f (); - dir_ = s->dir_; - beam_dir_ = s->beam_dir_; - mult_i_ = s->mult_i_; + stem_l_ = s; + x_ = stem_l_->hpos_f (); + dir_ = stem_l_->dir_; + beam_dir_ = stem_l_->beam_dir_; + mult_i_ = stem_l_->mult_i_; /* [TODO] @@ -43,33 +44,34 @@ Stem_info::Stem_info (Stem const *s) */ - Real internote_f = s->paper ()->internote_f (); - Real interbeam_f = s->paper ()->interbeam_f (mult_i_); - Real beam_f = s->paper ()->beam_thickness_f (); + Real internote_f = stem_l_->paper ()->internote_f (); + Real interbeam_f = stem_l_->paper ()->interbeam_f (mult_i_); + Real beam_f = stem_l_->paper ()->beam_thickness_f (); { static int i = 1; DOUT << "******" << i++ << "******\n" - << "begin_f: " << s->stem_begin_f () * dir_ - << "\nchord_f/i: " << s->chord_start_f () * dir_ / internote_f << '\n'; + << "begin_f: " << stem_l_->stem_begin_f () * dir_ + << "\nchord_f/i: " << stem_l_->chord_start_f () * dir_ / internote_f << '\n'; } /* For simplicity, we'll assume dir = UP and correct if dir = DOWN afterwards. */ - idealy_f_ = s->chord_start_f () * beam_dir_ / internote_f; + idealy_f_ = stem_l_->chord_start_f () * beam_dir_ / internote_f; idealy_f_ *= internote_f; - Real break_i = (int)rint (s->paper ()->get_var ("beam_multiple_break")); - Real min_stem1_f = s->paper ()->get_var ("beam_minimum_stem1"); - Real min_stem2_f = s->paper ()->get_var ("beam_minimum_stem2"); - Real ideal_stem1_f = s->paper ()->get_var ("beam_ideal_stem1"); - Real ideal_stem2_f = s->paper ()->get_var ("beam_ideal_stem2"); - Real shorten_f = s->paper ()->get_var ("forced_stem_shorten"); + Real break_i = (int)rint (stem_l_->paper ()->get_var ("beam_multiple_break")); + Real min_stem1_f = stem_l_->paper ()->get_var ("beam_minimum_stem1"); + Real min_stem2_f = stem_l_->paper ()->get_var ("beam_minimum_stem2"); + Real ideal_stem1_f = stem_l_->paper ()->get_var ("beam_ideal_stem1"); + Real ideal_stem2_f = stem_l_->paper ()->get_var ("beam_ideal_stem2"); + Real shorten_f = stem_l_->paper ()->get_var ("forced_stem_shorten"); if (!beam_dir_ || (beam_dir_ == dir_)) + /* normal (beamed) stem */ { idealy_f_ += interbeam_f * mult_i_; miny_f_ = idealy_f_; @@ -87,13 +89,13 @@ Stem_info::Stem_info (Stem const *s) } /* - stems in unnatural (forced) direction are shortened - central line is never 'forced' + stems in unnatural (forced) direction are shortened but + - central line is never 'forced' + - beamed stems are shortened only by beam itself */ - if (((int)s->chord_start_f ()) && (s->dir_ != s->get_default_dir ())) + if (!mult_i_ && ((int)stem_l_->chord_start_f ()) && (stem_l_->dir_ != stem_l_->get_default_dir ())) { idealy_f_ -= shorten_f; -// miny_f_ = miny_f_ 0) * beam_f + interbeam_f * (mult_i_ - 1)); } else + /* knee */ { idealy_f_ -= beam_f; maxy_f_ = idealy_f_; miny_f_ = -INT_MAX; - // B"arenreiter if (mult_i_ < break_i) { idealy_f_ -= ideal_stem1_f;