]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 4127: allow mid-measure \time
authorDan Eble <nine.fierce.ballads@gmail.com>
Wed, 8 Oct 2014 02:28:21 +0000 (22:28 -0400)
committerDavid Kastrup <dak@gnu.org>
Mon, 13 Oct 2014 13:52:35 +0000 (15:52 +0200)
\time is now allowed in mid measure provided that \partial appears at
the same timestep.

Documentation changes include some clean-up of index entries related
to time signatures.

Documentation/changes.tely
Documentation/notation/ancient.itely
Documentation/notation/changing-defaults.itely
Documentation/notation/rhythms.itely
input/regression/time-signature-midmeasure-warning.ly [new file with mode: 0644]
input/regression/time-signature-midmeasure.ly
lily/partial-iterator.cc
lily/time-signature-engraver.cc
scm/define-context-properties.scm
scm/define-music-callbacks.scm

index b714fe5d941628cfc9aa5017160e36627583c85b..1dd439dfb0b601b2d7f85e9830d3a8abd4885023 100644 (file)
@@ -61,6 +61,16 @@ which scares away people.
 
 @end ignore
 
+@item
+It is now possible to use @code{\time} and @code{\partial}
+together to change the time signature in mid measure.
+
+@lilypond[verbatim,quote,relative=1]
+\override Score.BarNumber.break-visibility = #end-of-line-invisible
+\partial 4 \time 3/4 f4 | 2 4 | 2 \bar "||"
+\time 9/8 \partial 4. f8 8 8 | 2. 8 8 8 |
+@end lilypond
+
 @item
 It is now possible to override the @code{text} property of
 chord names.
index 9d74daf0627794f730e6e278a00f0a6dedbc06a5..8df2029c62e000c90de37cec14bdeb6cf7840c35 100644 (file)
@@ -536,7 +536,8 @@ The mensural g clef is mapped to the Petrucci g clef.
 @unnumberedsubsubsec Mensural time signatures
 
 @cindex mensuration sign
-@cindex time signatures
+@cindex time signature, mensural
+@cindex time signature style
 
 There is limited support for mensuration signs (which are similar to,
 but not exactly the same as time signatures).  The glyphs are hard-wired
index 49151b976721fa55e6cd2cae275aa70b7fba9d3a..6d6b724cff20a1d7b6c745218af1cf12ef46b854 100644 (file)
@@ -756,7 +756,7 @@ within the measure, etc.  By moving these engraver from @code{Score} to
 time signature.
 
 @cindex polymetric scores
-@cindex Time signatures, multiple
+@cindex time signature, multiple
 
 @lilypond[quote,verbatim]
 \score {
index 77b2d7ecc319e40f35a4f1fd9cba234ee48f047f..a2c506cbbe4485d747e37f3be2c95d9d583380e6 100644 (file)
@@ -1027,7 +1027,9 @@ The time signature is set as follows:
 \time 3/4 c2.
 @end lilypond
 
-@cindex time signature, visibility of
+Mid-measure time signature changes are covered in @ref{Upbeats}.
+
+@cindex time signature visibility
 
 Time signatures are printed at the beginning of a piece
 and whenever the time signature changes.  If a change takes place
@@ -1374,29 +1376,22 @@ Internals Reference:
 @cindex measure, partial
 @cindex measure, pickup
 @cindex pickup measure
+@cindex time signature, mid-measure
 
 @funindex measurePosition
 @funindex \partial
 @funindex partial
 
 Partial or pick-up measures, such as an @emph{anacrusis} or an
-@emph{upbeat}, are entered using the @code{\partial} command,
+@emph{upbeat}, are entered using the @code{\partial} command:
 
 @example
 \partial @var{duration}
 @end example
 
-@noindent
-where @code{@var{duration}} is the @emph{remaining} length of the
-partial measure @emph{before} the start of the next full measure.
-
-@lilypond[quote,verbatim,relative=1]
-\time 3/4
-\partial 8
-e8 | a4 c8 b c4 |
-@end lilypond
-
-The @var{duration} can be any value less than a full measure:
+When @code{\partial} is used at the beginning of a score,
+@code{@var{duration}} is the length of the music preceding the
+first bar.
 
 @lilypond[quote,verbatim,relative=1]
 \time 3/4
@@ -1404,28 +1399,23 @@ The @var{duration} can be any value less than a full measure:
 r4 e8 | a4 c8 b c4 |
 @end lilypond
 
-@code{\partial @var{duration}} can also be written as:
-
-@example
-\set Timing.measurePosition -@var{duration}
-@end example
-
-So the first example above could be written:
+When @code{\partial} is used after the beginning of a score,
+@code{@var{duration}} is the @emph{remaining} length of the
+current measure.  It does not create a new numbered bar.
 
 @lilypond[quote,verbatim,relative=1]
-\time 3/4
-\set Timing.measurePosition = #(ly:make-moment -1/8)
-e8 | a4 c8 b c4 |
+\set Score.barNumberVisibility = #all-bar-numbers-visible
+\override Score.BarNumber.break-visibility =
+          #end-of-line-invisible
+\time 9/8
+d'4.~ 4 d8 d( c) b | c4.~ 4. \bar "||"
+\time 12/8
+\partial 4.
+c8( d) e | f2.~ 4 f8 a,( c) f |
 @end lilypond
 
-The property @code{measurePosition} contains a rational number,
-which is usually positive and indicates how much of the measure
-has passed at this point.  @code{\partial @var{duration}} is
-defined such that no numbered bar gets created: when used at the
-beginning of a score, @code{measurePosition} is set to a
-negative number, implying that the current bar will be
-@emph{preceded} by additional material.  When used elsewhere, it
-moves the requested distance before the @emph{end} of the bar.
+The @code{\partial} command is @emph{required} when the time
+signature changes in mid measure, but it may also be used alone.
 
 @lilypond[quote,verbatim,relative=1]
 \set Score.barNumberVisibility = #all-bar-numbers-visible
@@ -1441,6 +1431,9 @@ r8 e8 | a4
 c8 b[ c b] |
 @end lilypond
 
+The @code{\partial} command sets the @code{Timing.measurePosition}
+property, which is a rational number that indicates how much of
+the measure has passed.
 
 @seealso
 Music Glossary:
@@ -1594,8 +1587,8 @@ stretches of unmetered music to permit breaking:
 
 @cindex double time signatures
 @cindex signatures, polymetric
-@cindex time signatures, polymetric
-@cindex time signatures, double
+@cindex time signature, polymetric
+@cindex time signature, double
 @cindex polymetric signatures
 @cindex meter, polymetric
 
diff --git a/input/regression/time-signature-midmeasure-warning.ly b/input/regression/time-signature-midmeasure-warning.ly
new file mode 100644 (file)
index 0000000..3481409
--- /dev/null
@@ -0,0 +1,15 @@
+\version "2.19.16"
+
+\header {
+  texidoc = "Mid-measure time signature changes not accompanied by
+\\partial generate warnings."
+}
+
+#(ly:expect-warning "mid-measure time signature without \\partial")
+
+\score {
+  \relative {
+    \partial 8 \time 4/4
+    a'8 | d4 \time 3/4 cis b
+  }
+}
index 10b5891100ffa1206420b27fea28c80ad9ec5317..ed3d34f2adcaa80fe9157e814a18347699bfaa1e 100644 (file)
@@ -1,28 +1,47 @@
-\version "2.19.4"
+\version "2.19.16"
 
 \header {
-  texidoc = "Time signature changes in midmeasure generate warnings,
-except in an anacrusis or when @code{ignoreBarChecks} is true.
-@code{measurePosition} is reset to 0, so a full measure follows, regardless
-of the original position.
+  texidoc = "Mid-measure time signature changes must be accompanied by
+\\partial.
 
-This example should end at bar 3, with no barline before the 2/4."
+In this example, no bar numbers should be omitted or repeated, and all
+double bar lines should have parenthesized bar numbers consistent with
+the single bar lines.  Both scores should look identical.
+
+@itemize @bullet
+@item \\time 2/4 occurs at a negative position
+@item \\time 6/8 occurs at a position less than the new measure length
+@item \\time 3/8 occurs at a position equal to the new measure length
+@item \\time 3/16 occurs at a position greater than the new measure length
+@end itemize"
 }
 
-#(ly:expect-warning (_ "\\time in mid-measure at 1/4"))
+\score {
+  \relative {
+    \set Score.barNumberVisibility = #all-bar-numbers-visible
+    \override Score.BarNumber.break-visibility = #all-visible
+    \time 2/4 \partial 8
+    a'8 | d4
+    \bar "||" \time 6/8 \partial 4.
+    cis8 b a | \barNumberCheck 2 g2. | \barNumberCheck 3 g4.
+    \bar "||" \time 3/8 \partial 4.
+    f4. | \barNumberCheck 4 f4. | \barNumberCheck 5 f4
+    \bar "||" \time 3/16 \partial 8
+    fis8 | \barNumberCheck 6 g16 a g | \barNumberCheck 7
+  }
+}
 
 \score {
   \relative {
+    \set Score.barNumberVisibility = #all-bar-numbers-visible
     \override Score.BarNumber.break-visibility = #all-visible
     \partial 8 \time 2/4
     a'8 | d4
-    \time 6/8 \partial 4.
-    cis8 b a | g4. \barNumberCheck 2
-    \set Timing.ignoreBarChecks = ##t
-    \time 12/8
-    fis4. e d
-    \time 2/4
-    \set Timing.ignoreBarChecks = ##f
-    a'2 | \barNumberCheck 3
+    \bar "||" \partial 4. \time 6/8
+    cis8 b a | \barNumberCheck 2 g2. | \barNumberCheck 3 g4.
+    \bar "||" \partial 4. \time 3/8
+    f4. | \barNumberCheck 4 f4. | \barNumberCheck 5 f4
+    \bar "||" \partial 8 \time 3/16
+    fis8 | \barNumberCheck 6 g16 a g | \barNumberCheck 7
   }
 }
index 723391020913a08dab5785a36ca4acde7759d83e..a5dd82ab1efc843f40638d9d6b36516358e7972a 100644 (file)
@@ -41,8 +41,27 @@ Partial_iterator::process (Moment m)
       = Duration::unsmob (get_music ()->get_property ("duration")))
     {
       Moment length = Moment (dur->get_length ());
-      if (get_outlet ()->now_mom () > 0)
+
+      // Partial_iterator is an iterator rather than an engraver,
+      // so the active context it is getting called in does not
+      // depend on which context definition the engraver might be
+      // defined.
+      //
+      // Using where_defined to find the context where
+      // measurePosition should be overwritten does not actually
+      // work since the Timing_translator does not set
+      // measurePosition when initializing.
+
+      Context *timing = Context::unsmob
+                        (scm_call_2 (ly_lily_module_constant ("ly:context-find"),
+                                     get_outlet ()->self_scm (),
+                                     ly_symbol2scm ("Timing")));
+
+      if (!timing)
+        programming_error ("missing Timing in \\partial");
+      else if (get_outlet ()->now_mom () > 0)
         {
+          timing->set_property ("partialBusy", ly_bool2scm (true));
           Global_context *tg = get_outlet ()->get_global_context ();
           tg->add_finalization (scm_list_3 (finalization_proc,
                                             get_outlet ()->self_scm (),
@@ -50,31 +69,12 @@ Partial_iterator::process (Moment m)
         }
       else
         {
-          // Partial_iterator is an iterator rather than an engraver,
-          // so the active context it is getting called in does not
-          // depend on which context definition the engraver might be
-          // defined.
-          //
-          // Using where_defined to find the context where
-          // measurePosition should be overwritten does not actually
-          // work since the Timing_translator does not set
-          // measurePosition when initializing.
-
-          Context *timing = Context::unsmob
-            (scm_call_2 (ly_lily_module_constant ("ly:context-find"),
-                         get_outlet ()->self_scm (),
-                         ly_symbol2scm ("Timing")));
-          if (!timing)
-            programming_error ("missing Timing in \\partial");
-          else
-            {
-              Moment mp = robust_scm2moment
-                (timing->get_property ("measurePosition"),
-                 Rational (0));
-              mp.main_part_ = 0;
-              timing->set_property
-                ("measurePosition", (mp - length).smobbed_copy ());
-            }
+          Moment mp = robust_scm2moment
+                      (timing->get_property ("measurePosition"),
+                       Rational (0));
+          mp.main_part_ = 0;
+          timing->set_property
+          ("measurePosition", (mp - length).smobbed_copy ());
         }
     }
   else
@@ -104,5 +104,7 @@ Partial_iterator::finalization (SCM ctx, SCM length)
   mp.main_part_ = measure_length (timing);
   timing->set_property ("measurePosition",
                         (mp - *Moment::unsmob (length)).smobbed_copy ());
+  timing->unset_property (ly_symbol2scm ("partialBusy"));
+
   return SCM_UNSPECIFIED;
 }
index 8c444e57471d86cd13ecfc1ed5d7d1063b789e3e..38989dc882db6d97595fbed75635f83210994efb 100644 (file)
@@ -22,6 +22,7 @@
 #include "item.hh"
 #include "international.hh"
 #include "misc.hh"
+#include "moment.hh"
 #include "stream-event.hh"
 #include "time-signature.hh"
 #include "warn.hh"
@@ -70,11 +71,21 @@ Time_signature_engraver::listen_time_signature (Stream_event *ev)
 void
 Time_signature_engraver::process_music ()
 {
+  if (time_signature_)
+    return;
+
   SCM fr = get_property ("timeSignatureFraction");
-  if (!time_signature_
-      && last_time_fraction_ != fr
+  if (last_time_fraction_ != fr
       && scm_is_pair (fr))
     {
+      time_signature_ = make_item ("TimeSignature", time_cause_);
+      time_signature_->set_property ("fraction", fr);
+
+      // Todo: "implicit" does not seem perfectly accurate (issue 4151)
+      if (last_time_fraction_ == SCM_BOOL_F)
+        time_signature_->set_property ("break-visibility",
+                                       get_property ("implicitTimeSignatureVisibility"));
+
       int den = scm_to_int (scm_cdr (fr));
       if (den != (1 << intlog2 (den)))
         {
@@ -83,18 +94,11 @@ Time_signature_engraver::process_music ()
 
             OTOH, Tristan Keuris writes 8/20 in his Intermezzi.
           */
-          warning (_f ("strange time signature found: %d/%d",
-                       int (scm_to_int (scm_car (fr))),
-                       den));
+          time_signature_->warning (_f ("strange time signature found: %d/%d",
+                                        int (scm_to_int (scm_car (fr))),
+                                        den));
         }
 
-      time_signature_ = make_item ("TimeSignature", time_cause_);
-      time_signature_->set_property ("fraction", fr);
-
-      if (last_time_fraction_ == SCM_BOOL_F)
-        time_signature_->set_property ("break-visibility",
-                                       get_property ("implicitTimeSignatureVisibility"));
-
       last_time_fraction_ = fr;
     }
 }
@@ -102,6 +106,14 @@ Time_signature_engraver::process_music ()
 void
 Time_signature_engraver::stop_translation_timestep ()
 {
+  if (time_signature_ && (time_cause_ != SCM_EOL))
+    {
+      Moment *mp = Moment::unsmob (get_property ("measurePosition"));
+      if (mp && (mp->main_part_ > Rational (0))
+          && !to_boolean (get_property ("partialBusy")))
+        time_signature_->warning ("mid-measure time signature without \\partial");
+    }
+
   time_signature_ = 0;
   time_cause_ = SCM_EOL;
 }
@@ -118,6 +130,7 @@ ADD_TRANSLATOR (Time_signature_engraver,
 
                 /* read */
                 "implicitTimeSignatureVisibility "
+                "partialBusy "
                 "timeSignatureFraction ",
 
                 /* write */
index 4b458c013c0b42790f98ea89745a5464f04f0417..a3fe8e90ed3198d3619e3695233f7de7a900b37f 100644 (file)
@@ -731,6 +731,9 @@ This can be used to signal melismas on top of those automatically
 detected.")
 
 
+     (partialBusy ,boolean? "Signal that \\partial acts at the current timestep.")
+
+
      (quotedCueEventTypes ,list? "A list of symbols, representing the
 event types that should be duplicated for @code{\\cueDuring} commands.")
      (quotedEventTypes ,list? "A list of symbols, representing the
index a6441d1e21798e58296d17fcbff0d376a0bb0ac9..24281a883846ac64d0e7aa6293b2657ce3ff1499 100644 (file)
@@ -102,19 +102,7 @@ to be used by the sequential-iterator"
                            structure))
                       (beaming-exception
                        (beam-exceptions fraction time-signature-settings))
-                      (new-measure-length (ly:make-moment num den))
-                      (pos (ly:context-property context 'measurePosition)))
-                 ;;\time is OK at a negative measurePosition (after \partial),
-                 ;;but at a positive position it's probably a mistake, so warn
-                 ;;(like a barcheck) and reset it to 0 to prevent errors.
-                 (if (> (ly:moment-main pos) 0)
-                     (begin
-                       (if (not (ly:context-property context 'ignoreBarChecks #f))
-                           (ly:music-warning music
-                                             (_ "\\time in mid-measure at ~A")
-                                             (ly:moment-main pos)))
-                       (ly:context-set-property!
-                        context 'measurePosition (ly:make-moment 0))))
+                      (new-measure-length (ly:make-moment num den)))
                  (ly:context-set-property!
                   context 'timeSignatureFraction fraction)
                  (ly:context-set-property!