]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 2470: introduce completionUnit
authorBenkő Pál <benko.pal@gmail.com>
Sat, 14 Apr 2012 08:21:02 +0000 (10:21 +0200)
committerDavid Kastrup <dak@gnu.org>
Sat, 14 Apr 2012 08:23:20 +0000 (10:23 +0200)
enable Completion_heads_engraver to work in sub-bar units

input/regression/completion-heads-unit.ly [new file with mode: 0644]
lily/completion-note-heads-engraver.cc
scm/define-context-properties.scm

diff --git a/input/regression/completion-heads-unit.ly b/input/regression/completion-heads-unit.ly
new file mode 100644 (file)
index 0000000..af3152b
--- /dev/null
@@ -0,0 +1,26 @@
+\version "2.15.37"
+
+\header {
+texidoc = "
+Note head completion may be broken into sub-bar units by setting the
+@code{completionUnit} property.
+"
+}
+
+\layout {
+  \context {
+    \Voice
+    \remove "Note_heads_engraver"
+    \consists "Completion_heads_engraver"
+  }
+}
+
+\context Staff \relative f {
+  \time 9/8
+  \set completionUnit = #(ly:make-moment 3 8)
+  g'1.. g2
+  \time 6/4
+  \set completionUnit = #(ly:make-moment 1 4)
+  \set tupletSpannerDuration = #(ly:make-moment 1 4)
+  \times 2/3 { e4 c8 f g a4 b8 c4 b8 a4 g8 a e f4 }
+}
index 64705a4abde14cfb18f5f5a6b0dd302a22e316cf..973fb4f28dbb14a1ca3d79c8819ee8670f60cd29 100644 (file)
@@ -35,6 +35,7 @@ using namespace std;
 #include "tie.hh"
 #include "tie-column.hh"
 #include "warn.hh"
+#include "misc.hh"
 
 #include "translator.icc"
 
@@ -47,7 +48,7 @@ using namespace std;
   Every time process_music () is called and there are note events, we
   figure out how long the note to typeset should be. It should be no
   longer than what's specified, than what is left to do and it should
-  not cross barlines.
+  not cross barlines or sub-bar units.
 
   We copy the events into scratch note events, to make sure that we get
   all durations exactly right.
@@ -69,7 +70,7 @@ class Completion_heads_engraver : public Engraver
   Rational do_nothing_until_;
   Rational factor_;
 
-  Moment next_barline_moment ();
+  Moment next_moment (Rational const &);
   Item *make_note_head (Stream_event *);
 
 public:
@@ -105,10 +106,10 @@ Completion_heads_engraver::listen_note (Stream_event *ev)
 }
 
 /*
-  The duration _until_ the next bar line.
+  The duration _until_ the next bar line or completion unit
 */
 Moment
-Completion_heads_engraver::next_barline_moment ()
+Completion_heads_engraver::next_moment (Rational const &note_len)
 {
   Moment *e = unsmob_moment (get_property ("measurePosition"));
   Moment *l = unsmob_moment (get_property ("measureLength"));
@@ -117,7 +118,40 @@ Completion_heads_engraver::next_barline_moment ()
       return Moment (0, 0);
     }
 
-  return (*l - *e);
+  Moment result = *l - *e;
+  Moment const *unit = unsmob_moment (get_property ("completionUnit"));
+
+  if (unit)
+    {
+      Rational const now_unit = e->main_part_ / unit->main_part_;
+      if (now_unit.den() > 1)
+        {
+          /*
+            within a unit - go to the end of that
+          */
+          result = unit->main_part_
+            * (Rational (1) - (now_unit - now_unit.trunc_rat ()));
+        }
+      else
+        {
+          /*
+            at the beginning of a unit:
+            take a power-of-two number of units, but not more than required,
+            since then the Duration constructor destroys the unit structure
+          */
+          if (note_len < result.main_part_)
+            result.main_part_ = note_len;
+          Rational const step_unit = result.main_part_ / unit->main_part_;
+          if (step_unit.den () < step_unit.num ())
+            {
+              int const log2
+                = intlog2 (int (step_unit.num () / step_unit.den ()));
+              result.main_part_ = unit->main_part_ * Rational (1 << log2);
+            }
+        }
+    }
+
+  return result;
 }
 
 Item *
@@ -168,10 +202,10 @@ Completion_heads_engraver::process_music ()
       factor_ = note_dur.factor ();
       left_to_do_ = orig->get_length ();
     }
-  Moment nb = next_barline_moment ();
+  Moment nb = next_moment (note_dur.get_length ());
   if (nb.main_part_ && nb < note_dur.get_length ())
     {
-      if (factor_.denominator () == 1 && factor_ > Rational (1, 1))
+      if (factor_.denominator () == 1 && factor_.numerator () > 1)
         note_dur = Duration (nb.main_part_, false);
       else
         note_dur = Duration (nb.main_part_ / factor_, false).compressed (factor_);
index ff29b144c966e91d8179f310664b74f66f9904a8..15c717ffd1d480ba969caa7aac4987991db97798 100644 (file)
@@ -177,6 +177,7 @@ Values of 7 and -7 are common.")
 symbol go, measured in half staff spaces from the center of the
 staff.")
      (completionBusy ,boolean? "Whether a completion-note head is playing.")
+     (completionUnit ,ly:moment? "Sub-bar unit of completion.")
      (connectArpeggios ,boolean? "If set, connect arpeggios across
 piano staff.")
      (countPercentRepeats ,boolean? "If set, produce counters for