Jump to content

Big time signatures

From LilyPond wiki
Revision as of 11:42, 17 November 2025 by Lazy (talk | contribs) (Created page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

In some modern conducting scores it is common to not print individual time signatures for each staff, but to print large time signatures either over the whole system or over the instrument groups. This code implements such behaviour by

  1. Creating a new `BigTimeSignature` spanner grob which spans multiple time signatures and prints an enlarged signatures over their extent
  2. Creates an engraver that collects all time signatures and creates a `BigTimeSignature` spanner on them

\version "2.24"

%%% Define a new `BigTimeSignature` spanner
#(define (big-time-signature::print grob)
   (let*
    ((elts (ly:grob-object grob 'elements)) ; time-sig grobs
     (ref (ly:grob-common-refpoint-of-array grob elts Y)) ; common refpoint
     (exts (map (lambda (x) (ly:grob-extent x ref Y)) (ly:grob-array->list elts))) ; extents of all ts-grobs
     (full-ext (cons (apply min (map car exts)) (apply max (map cdr exts)))) ; full extent of ts column
     (stc (ly:grob-property (ly:grob-array-ref elts 0) 'stencil)) ; the stencil of one time signature
     (stc-ext-y (car exts)) ; the Y-extent of the time sig stencil
     (f (/ (interval-length full-ext) (interval-length stc-ext-y)))) ; scaling factor for the stencil
    (ly:grob-set-parent! grob Y ref) ; Y-parent should be System = ref already, but just in case make sure
    (ly:stencil-translate-axis ; shift resulting stencil to begin of time sig column
     (ly:stencil-aligned-to (ly:stencil-scale stc 1 f) Y DOWN) ; scale stencil and make sure it is not shifted
     (car full-ext) Y)))

#(set! all-grob-descriptions
  (sort
   (cons
    ((@@ (lily) completize-grob-entry)
     `(BigTimeSignature
       . ((stencil . ,big-time-signature::print)
          (meta
           . ((class . Spanner)
              (interfaces . (spanner-interface))
              (description . "A big time signature"))))))
    all-grob-descriptions)
   alist<?))

\layout {
  \context {
    \Global
    \grobdescriptions #all-grob-descriptions
  }
}


%%% Create engraver for big time signatures
#(define (big-time-signature-engraver context)
   (let ((time-sig '()))
     (make-engraver
      (acknowledgers
       ((time-signature-interface engraver grob source-engraver) ; collect time signature grobs
        (set! time-sig (cons grob time-sig))))
      ((process-acknowledged engraver)
       (if (not (null? time-sig)) ; if any time-signatures
           (let ; create BigTimeSignature spanner with time sigs at parents
            ((spanner (ly:engraver-make-spanner engraver 'BigTimeSignature '())))
            (ly:spanner-set-bound! spanner UP (first time-sig))
            (ly:spanner-set-bound! spanner DOWN (first time-sig))
            (ly:grob-set-parent! spanner X (first time-sig)) ; set one time signature as X-parent for proper alignment
            (ly:grob-set-object! spanner 'elements (ly:grob-list->grob-array time-sig))))
       (set! time-sig '())))))


%%% Example (score level)
\score {
  \layout {
    \context {
      \Score
      \consists #big-time-signature-engraver
      \override TimeSignature.transparent = ##t
    }
  }

  <<
    \new Staff {
      \numericTimeSignature
      c''1 \time 3/4 d''2.
    }
    \new Staff {
      c''1 \time 3/4 d''2.
    }
    \new Staff {
      c''1 \time 3/4 d''2.
    }
  >>
}


%%% Example (staff group level)
\score {
  \layout {
    \context {
      \StaffGroup
      \consists #big-time-signature-engraver
      \override TimeSignature.transparent = ##t
    }
  }

  <<
    \new Staff {
      \numericTimeSignature
      c''1 \time 3/4 d''2.
    }
    <<
      \new StaffGroup <<
        \new Staff {
          c''1 \time 3/4 d''2.
        }
        \new Staff {
          c''1 \time 3/4 d''2.
        }
      >>
    >>
    <<
      \new StaffGroup <<
        \new Staff {
          c''1 \time 3/4 d''2.
        }
        \new Staff {
          c''1 \time 3/4 d''2.
        }
        \new Staff {
          c''1 \time 3/4 d''2.
        }
      >>
    >>
  >>
}