]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fix 638: Fix autobeaming in 4 4 time.
authorCarl Sorensen <c_sorensen@byu.edu>
Sat, 29 Aug 2009 16:28:04 +0000 (10:28 -0600)
committerCarl Sorensen <c_sorensen@byu.edu>
Thu, 24 Dec 2009 18:20:01 +0000 (11:20 -0700)
Add rechecking for auto-beams when shortest duration changes.

Add argument for test_moment to calls checking for beam start and end
points.

Create split procedures for stems_ and Beaming_pattern

input/regression/auto-beam-recheck.ly [new file with mode: 0644]
lily/auto-beam-engraver.cc
lily/beam.cc
lily/beaming-pattern.cc
lily/include/beaming-pattern.hh
scm/auto-beam.scm

diff --git a/input/regression/auto-beam-recheck.ly b/input/regression/auto-beam-recheck.ly
new file mode 100644 (file)
index 0000000..54f3614
--- /dev/null
@@ -0,0 +1,15 @@
+\version "2.13.10"
+\header {
+
+  texidoc = "In 4/4 time, the first and second and third and fourth
+beats should be beamed together if only eighth notes are involved.
+If any shorter notes are included, each beat should be beamed separately."
+
+}
+\layout { ragged-right = ##t }
+
+\relative c'' {
+  \repeat unfold 8 { a8} |
+  a8 a a a16 a a8 a  a16 a a8 |
+  r16 a8. a8 a16 a r8. a16 a8 a16 a |
+}
index c4635ed62bc986a74f844c584a071b6c3989b048..a3d38af5b3dd4c76d842f7d4806eb514d721c5ed 100644 (file)
@@ -51,19 +51,21 @@ protected:
   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_;
@@ -87,8 +89,8 @@ private:
 
   Beaming_options beaming_options_;
   Beaming_options finished_beaming_options_;
-  
-  
+
+
   void check_bar_property ();
 };
 
@@ -108,7 +110,7 @@ Auto_beam_engraver::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 ();
     }
 }
@@ -116,25 +118,25 @@ Auto_beam_engraver::check_bar_property ()
 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 ();
     }
 }
@@ -159,36 +161,37 @@ Auto_beam_engraver::listen_beam_forbid (Stream_event *ev)
 }
 
 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 ();
     }
@@ -260,7 +263,7 @@ Auto_beam_engraver::end_beam ()
   else
     {
       finished_beam_ = create_beam ();
-      
+
       if (finished_beam_)
        {
          announce_end_grob (finished_beam_, SCM_EOL);
@@ -283,7 +286,7 @@ Auto_beam_engraver::typeset_beam ()
     {
       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;
@@ -381,13 +384,22 @@ Auto_beam_engraver::acknowledge_stem (Grob_info info)
   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;
@@ -398,24 +410,98 @@ Auto_beam_engraver::acknowledge_stem (Grob_info info)
   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 ();
@@ -448,7 +534,7 @@ ADD_TRANSLATOR (Auto_beam_engraver,
                "beamSettings "
                "beatLength "
                "subdivideBeams ",
-               
+
                /* write */
                ""
                );
index 5e26628fc07c4d3f5c2d82c88447d196be4477a3..4c71860664efd110c7ffb30ba0b0fc0a703fb249 100644 (file)
@@ -108,7 +108,7 @@ Beam::get_beam_translation (Grob *me)
   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;
@@ -136,15 +136,15 @@ SCM
 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);
@@ -173,7 +173,7 @@ Beam::calc_direction (SCM smob)
 
          return SCM_UNSPECIFIED;
        }
-      else 
+      else
        {
          Grob *stem = first_normal_stem (me);
 
@@ -182,8 +182,8 @@ Beam::calc_direction (SCM smob)
          */
          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"));
@@ -194,7 +194,7 @@ Beam::calc_direction (SCM smob)
     {
       if (!dir)
        dir = get_default_dir (me);
-      
+
       consider_auto_knees (me);
     }
 
@@ -202,7 +202,7 @@ Beam::calc_direction (SCM smob)
     {
       set_stem_directions (me, dir);
     }
-  
+
   return scm_from_int (dir);
 }
 
@@ -255,12 +255,12 @@ SCM
 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++)
@@ -299,7 +299,7 @@ Beam::calc_beaming (SCM smob)
       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))
@@ -309,7 +309,7 @@ Beam::calc_beaming (SCM smob)
              last_int.add_point (np);
            }
        }
-      
+
       if (scm_ilength (scm_cdr (this_beaming)) > 0)
        {
          last_beaming = this_beaming;
@@ -327,7 +327,7 @@ operator <(Beam_stem_segment const &a,
   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)
@@ -345,7 +345,7 @@ 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);
 
@@ -381,13 +381,13 @@ Beam::get_beam_segments (Grob *me_grob, Grob **common)
              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;
@@ -397,9 +397,9 @@ Beam::get_beam_segments (Grob *me_grob, Grob **common)
              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);
@@ -450,12 +450,12 @@ Beam::get_beam_segments (Grob *me_grob, Grob **common)
              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.
@@ -531,7 +531,7 @@ Beam::get_beam_segments (Grob *me_grob, Grob **common)
            }
          while (flip (&event_dir) != LEFT);
        }
-      
+
     }
 
   return segments;
@@ -553,7 +553,7 @@ Beam::print (SCM grob)
     }
   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);
     }
@@ -579,7 +579,7 @@ Beam::print (SCM grob)
   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 ++)
     {
@@ -588,18 +588,18 @@ Beam::print (SCM grob)
        {
          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))
@@ -608,10 +608,10 @@ Beam::print (SCM grob)
       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
@@ -637,7 +637,7 @@ Beam::print (SCM grob)
   the_beam.translate_axis (-me->relative_coordinate (commonx, X_AXIS), X_AXIS);
   return the_beam.smobbed_copy ();
 }
+
 Direction
 Beam::get_default_dir (Grob *me)
 {
@@ -691,7 +691,7 @@ 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])))
@@ -704,7 +704,7 @@ Beam::get_default_dir (Grob *me)
     dir = d;
   else
     dir = to_dir (me->get_property ("neutral-direction"));
-  
+
   return dir;
 }
 
@@ -864,14 +864,14 @@ set_minimum_dy (Grob *me, Real *dy)
     }
 }
 
-  
+
 
 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
   */
@@ -895,7 +895,7 @@ Beam::calc_stem_shorten (SCM smob)
 
   shorten *= forced_fraction;
 
-  
+
   if (shorten)
     return scm_from_double (shorten);
 
@@ -909,7 +909,7 @@ Beam::no_visible_stem_positions (Grob *me, Interval default_value)
   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++)
@@ -1144,7 +1144,7 @@ Beam::slope_damping (SCM smob, SCM posns)
   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);
@@ -1154,7 +1154,7 @@ Beam::slope_damping (SCM smob, SCM posns)
       me->set_property ("least-squares-dy", scm_from_double (0));
       damping = 0;
     }
-  
+
   if (damping)
     {
       scale_drul (&pos, Staff_symbol_referencer::staff_space (me));
@@ -1209,7 +1209,7 @@ where_are_the_whole_beams (SCM beaming)
    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);
@@ -1233,15 +1233,15 @@ Beam::calc_stem_y (Grob *me, Grob *stem, Grob **common,
 
   /*
     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)
@@ -1254,7 +1254,7 @@ Beam::calc_stem_y (Grob *me, Grob *stem, Grob **common,
   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)
 {
@@ -1265,7 +1265,7 @@ 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;
@@ -1370,7 +1370,7 @@ Beam::forced_stem_count (Grob *me)
       /* 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)
@@ -1419,7 +1419,7 @@ Beam::rest_collision_callback (SCM smob, SCM prev_offset)
     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)
@@ -1442,9 +1442,9 @@ Beam::rest_collision_callback (SCM smob, SCM prev_offset)
   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;
@@ -1474,7 +1474,7 @@ Beam::rest_collision_callback (SCM smob, SCM prev_offset)
    */
   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)
@@ -1601,7 +1601,7 @@ ADD_INTERFACE (Beam,
                "Damping slope which is considered zero for purposes of"
                " calculating direction penalties.\n"
                "@end table\n",
-              
+
               /* properties */
               "annotation "
               "auto-knee-gap "
index ab89bc386e90b05fceb8c184b0f7257fb4b7c6df..56623d99a63a2d714317f0d72c826af27aefb562 100644 (file)
@@ -245,6 +245,51 @@ Beaming_pattern::beamlet_count (int i, Direction d) const
   return infos_.at (i).beam_count_drul_[d];
 }
 
+Moment
+Beaming_pattern::start_moment (int i) const
+{
+  return infos_.at (i).start_moment_;
+}
+
+Moment
+Beaming_pattern::end_moment (int i) const
+{
+  Duration *dur = new Duration (2 + max (beamlet_count (i, LEFT),
+                                        beamlet_count (i, RIGHT)),
+                               0);
+
+  return infos_.at (i).start_moment_ + dur->get_length();
+}
+
+bool
+Beaming_pattern::invisibility (int i) const
+{
+  return infos_.at (i).invisible_;
+}
+
+/*
+    Split a beamin pattern at index i and return a new
+    Beaming_pattern containing the removed elements
+*/
+Beaming_pattern *
+Beaming_pattern::split_pattern (int i)
+{
+  Beaming_pattern* new_pattern=0;
+  int count;
+
+  new_pattern = new Beaming_pattern ();
+  for (vsize j=i+1; j<infos_.size (); j++)
+    {
+      count = max(beamlet_count (j, LEFT), beamlet_count(j, RIGHT));
+      new_pattern->add_stem (start_moment (j),
+                             count,
+                             invisibility (j));
+    }
+  for (vsize j=i+1; j<infos_.size (); )
+    infos_.pop_back ();
+  return (new_pattern);
+}
+
 void
 Beaming_options::from_context (Context *context)
 {
index eb813da275517094b8d8a645722362ace58bd2e8..bf56739d8e77230cfd8f3e59db2b41df5703b06d 100644 (file)
@@ -32,7 +32,7 @@ struct Beaming_options
   Moment measure_length_;
 
   Beaming_options ();
-  void from_context (Context*);  
+  void from_context (Context*);
 };
 
 struct Beam_rhythmic_element
@@ -42,7 +42,7 @@ struct Beam_rhythmic_element
 
   int rhythmic_importance_;
   bool invisible_;
-  
+
   Beam_rhythmic_element (Moment, int, bool);
   Beam_rhythmic_element ();
 
@@ -58,12 +58,16 @@ class Beaming_pattern
 {
 public:
   Beaming_pattern ();
-  
+
   void beamify (Beaming_options const&);
   void de_grace ();
   void add_stem (Moment d, int beams, bool invisible);
   int beamlet_count (int idx, Direction d) const;
-  
+  bool invisibility (int idx) const;
+  Moment start_moment (int idx) const;
+  Moment end_moment (int idx) const;
+  Beaming_pattern* split_pattern(int idx);
+
 private:
   vector<Beam_rhythmic_element> infos_;
   Direction flag_direction (Beaming_options const&, vsize) const;
index df31f369900f0233f09f451b8ce45b0b10ae49c4..c5ec73266dc0749dc7ecdbee32befc36067e0c96 100644 (file)
@@ -34,7 +34,7 @@
 ;;  2. exceptions for specific time signature, for specific duration type
 
 
-(define-public (default-auto-beam-check context dir test-beam)
+(define-public (default-auto-beam-check context dir measure-pos test-beam)
   (define (get name default)
     (let ((value (ly:context-property context name)))
       (if (not (null? value)) value default)))
@@ -60,7 +60,6 @@
                  (measure-length (get 'measureLength (ly:make-moment 1 1)))
                  (time-signature-fraction
                    (get 'timeSignatureFraction '(4 . 4)))
-                 (measure-pos (get 'measurePosition ZERO-MOMENT))
                  (settings (get 'beamSettings '()))
                  (function (if (= dir START) 'begin 'end))
                  (type (cons (ly:moment-main-numerator test-beam)