1

I would like to notate a piece proportionally in LilyPond in which different time signatures are layered polymetrically. To do this, I want to place the time signatures above the staves, or more precisely: above the bar lines. And I want to do this with a markup, because the space that the time signatures occupy before the first note (or rest) of a bar naturally remains if I simply move them vertically and horizontally with a \override command (e.g. with \override TimeSignature.extra-offset = #'(-2 . 8)). In short: the first note (or rest) of a bar is always set a little too far to the right than it should be according to a precise proportional notation.

So what I want to do is write a function in which I can insert the time signatures into the notes with a markup command. I'm thinking of something like this:

\version "2.25.2"

\relative c' {
  \override Score.TimeSignature. stencil = ##f 
   c4 d e f

 \mark \markup {
    \override #'(baseline-skip . 1.5)
    \override #'(font-size . 4.5)
    \override #'(font-name . "Bodoni72 Book")
    \override #'(whiteout-style . outline)
    \override #'(whiteout . 1)
    \override #'(extra-offset . -2)
    \column {
      \raise #0.5 \scale #'(0.8 . 0.8) "4" % Numerator of the time signature
      \raise #-0.5 \scale #'(0.8 . 0.8) "8" % Denominator of the time signature
    }
  }
  c8 d e f
}

It should be possible to pass numerators and denominators as arguments to such a function.

I am currently learning Scheme, but my knowledge is not yet sufficient to write such a function. Maybe someone can help me?

1 Answer 1

4

First things first: Such a function does exist (at least, a more powerful such function does exist):

\markup\compound-meter #'(4 8)

But if you really wanted to do your own function you’d need to define either a markup command (drawing the actual markup) or a scheme function (returning a markup to be drawn later). The markup command will be resolved later, which allows it to consider properties passed along. Of course you could also do a music function returning the actual mark event. See here how this would be done:

tsMarkup =
#(define-scheme-function (num den) (number? number?)
   #{
     \markup {
      \override #'(baseline-skip . 1.5)
      \override #'(font-size . 4.5)
      \override #'(font-name . "Bodoni72 Book")
      \override #'(whiteout-style . outline)
      \override #'(whiteout . 1)
      \override #'(extra-offset . -2)
      \column {
        \raise #0.5 \scale #'(0.8 . 0.8) #(number->string num) % Numerator of the time signature
        \raise #-0.5 \scale #'(0.8 . 0.8) #(number->string den) % Denominator of the time signature
      }
     }
   #})

#(define-markup-command (timesig layout props num den) (number? number?)
   (interpret-markup
    layout props
    #{
      \markup {
       \override #'(baseline-skip . 1.5)
       \override #'(font-size . 4.5)
       \override #'(font-name . "Bodoni72 Book")
       \override #'(whiteout-style . outline)
       \override #'(whiteout . 1)
       \override #'(extra-offset . -2)
       \column {
         \raise #0.5 \scale #'(0.8 . 0.8) #(number->string num) % Numerator of the time signature
         \raise #-0.5 \scale #'(0.8 . 0.8) #(number->string den) % Denominator of the time signature
       }
      }
    #}))

tsMark =
#(define-music-function (num den) (number? number?)
   #{
     \mark\markup {
      \override #'(baseline-skip . 1.5)
      \override #'(font-size . 4.5)
      \override #'(font-name . "Bodoni72 Book")
      \override #'(whiteout-style . outline)
      \override #'(whiteout . 1)
      \override #'(extra-offset . -2)
      \column {
        \raise #0.5 \scale #'(0.8 . 0.8) #(number->string num) % Numerator of the time signature
        \raise #-0.5 \scale #'(0.8 . 0.8) #(number->string den) % Denominator of the time signature
      }
     }
   #})

\relative c' {
  \override Score.TimeSignature. stencil = ##f 
  c4 d e f

  \time 4/8
  \mark\markup\compound-meter #'(4 8)
  c8 d e f
  \mark\markup\timesig #4 #8
  c8 d e f
  \mark \tsMarkup 4 8
  c8 d e f
  \tsMark 4 8
  c8 d e f
}

Generally instead of manually creating these marks it would be fairly simple though to include a custom Time signature engraver creating these marks for you (this might be a good example to understand how engravers work):

#(define (Top_time_signature_engraver context)
   (let* ((cause '()) (last-fraction #f))
     (make-engraver
      (listeners
       ((time-signature-event engraver event)
        (set! cause event)))
      ((process-music engraver)
       (let ((frac (ly:context-property context 'timeSignatureFraction)))
         (if (not (equal? frac last-fraction))
             (let ((grob (ly:engraver-make-grob engraver 'RehearsalMark cause)))
              (ly:grob-set-property! grob
                                     'text
                                     #{
                                       \markup {
                                        \override #'(baseline-skip . 1.5)
                                        \override #'(font-size . 4.5)
                                        \override #'(font-name . "Bodoni72 Book")
                                        \override #'(whiteout-style . outline)
                                        \override #'(whiteout . 1)
                                        \override #'(extra-offset . -2)
                                        \column {
                                          \raise #0.5 \scale #'(0.8 . 0.8) #(number->string (car frac)) % Numerator of the time signature
                                          \raise #-0.5 \scale #'(0.8 . 0.8) #(number->string (cdr frac)) % Denominator of the time signature
                                        }
                                       }
                                 #})))
         (set! last-fraction frac)
         (set! cause '()))))))

\layout {
  \context {
    \Staff
    \remove Time_signature_engraver
    \consists #Top_time_signature_engraver
  }
}

{ 4 4 4 4 \time 5/4 4 4 4 4 4 }

In simple words this engraver will always create a mark as soon as the time signature fraction changes. If a \time ... event exists it is provided as cause, which allows for things such as point and click.

This also allows you to specify the marks at whatever level you might want — Staff level:

\layout {
  \context {
    \Staff
    \remove Time_signature_engraver
    \consists #Top_time_signature_engraver
  }
}

<<
  \new StaffGroup <<
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 }
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 }
  >>
  \new StaffGroup <<
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 }
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 }
  >>
>>

Score level:

\layout {
  \context {
    \Staff
    \remove Time_signature_engraver
  }
  \context {
    \Score
    \consists #Top_time_signature_engraver
  }
}

<<
  \new StaffGroup <<
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 \time 7/8 8 8 8 8 8 8 8 }
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 \time 7/8 8 8 8 8 8 8 8}
  >>
  \new StaffGroup <<
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 \time 7/8 8 8 8 8 8 8 8}
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 \time 7/8 8 8 8 8 8 8 8}
  >>
>>

Staff group level:

\layout {
  \context {
    \Staff
    \remove Time_signature_engraver
  }
  \context {
    \StaffGroup
    \consists #Top_time_signature_engraver
  }
}

<<
  \new StaffGroup <<
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 \time 7/8 8 8 8 8 8 8 8 }
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 \time 7/8 8 8 8 8 8 8 8}
  >>
  \new StaffGroup <<
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 \time 7/8 8 8 8 8 8 8 8}
    \new Staff { 4 4 4 4 \time 5/4 4 4 4 4 4 \time 7/8 8 8 8 8 8 8 8}
  >>
>>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.