From: Dan Eble Date: Wed, 8 Oct 2014 02:28:21 +0000 (-0400) Subject: Issue 4127: allow mid-measure \time X-Git-Tag: release/2.19.16-1~4^2 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=61d0f3c7bebf2a9cdea56ff4e3b52e3e3510bf8a;p=lilypond.git Issue 4127: allow mid-measure \time \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. --- diff --git a/Documentation/changes.tely b/Documentation/changes.tely index b714fe5d94..1dd439dfb0 100644 --- a/Documentation/changes.tely +++ b/Documentation/changes.tely @@ -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. diff --git a/Documentation/notation/ancient.itely b/Documentation/notation/ancient.itely index 9d74daf062..8df2029c62 100644 --- a/Documentation/notation/ancient.itely +++ b/Documentation/notation/ancient.itely @@ -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 diff --git a/Documentation/notation/changing-defaults.itely b/Documentation/notation/changing-defaults.itely index 49151b9767..6d6b724cff 100644 --- a/Documentation/notation/changing-defaults.itely +++ b/Documentation/notation/changing-defaults.itely @@ -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 { diff --git a/Documentation/notation/rhythms.itely b/Documentation/notation/rhythms.itely index 77b2d7ecc3..a2c506cbbe 100644 --- a/Documentation/notation/rhythms.itely +++ b/Documentation/notation/rhythms.itely @@ -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 index 0000000000..348140952a --- /dev/null +++ b/input/regression/time-signature-midmeasure-warning.ly @@ -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 + } +} diff --git a/input/regression/time-signature-midmeasure.ly b/input/regression/time-signature-midmeasure.ly index 10b5891100..ed3d34f2ad 100644 --- a/input/regression/time-signature-midmeasure.ly +++ b/input/regression/time-signature-midmeasure.ly @@ -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 } } diff --git a/lily/partial-iterator.cc b/lily/partial-iterator.cc index 7233910209..a5dd82ab1e 100644 --- a/lily/partial-iterator.cc +++ b/lily/partial-iterator.cc @@ -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; } diff --git a/lily/time-signature-engraver.cc b/lily/time-signature-engraver.cc index 8c444e5747..38989dc882 100644 --- a/lily/time-signature-engraver.cc +++ b/lily/time-signature-engraver.cc @@ -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 */ diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm index 4b458c013c..a3fe8e90ed 100644 --- a/scm/define-context-properties.scm +++ b/scm/define-context-properties.scm @@ -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 diff --git a/scm/define-music-callbacks.scm b/scm/define-music-callbacks.scm index a6441d1e21..24281a8838 100644 --- a/scm/define-music-callbacks.scm +++ b/scm/define-music-callbacks.scm @@ -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!