Jump to content

Crossing staves

From LilyPond wiki

This snippet demonstrates how to create various types of staves where their lines actually cross other staves.

\version "2.24.0"

%% http://lsr.di.unimi.it/LSR/Item?id=1007
%% see also http://www.lilypondforum.de/index.php?topic=1416.msg7817#msg7817
%% see also http://lsr.di.unimi.it/LSR/Item?id=1005
%% Add by PPS on June 2015
%% Revised by WL in Oct 2023


% Make a chicane staff.
#(define-markup-command
   (chicane-staff layout props
                  length hcorr hpos bdist)
   (number? number? number? number?)
   "Draw a 'chicane' curved staff with length LENGTH.

Starting from a point stencil, the height must be adjusted manually;
HCORR specifies the height correction, HPOS the height position, and
BDIST corresponds to the 'basic-distance' value of the
'staff-staff-spacing' property."
   (interpret-markup
    layout props
    (markup
     (#:path
      0.1
      `((moveto 0 2)
        (curveto
         ,length 2
         ,(* length 0.5) ,(+ hcorr (* hpos bdist) 2)
         ,(* length 1.5) ,(+ hcorr (* hpos bdist) 2))
        (moveto 0 1)
        (curveto
         ,length 1
         ,(* length 0.5) ,(+ hcorr (* hpos bdist) 1)
         ,(* length 1.5) ,(+ hcorr (* hpos bdist) 1))
        (moveto 0 0)
        (curveto
         ,length 0
         ,(* length 0.5) ,(+ hcorr (* hpos bdist))
         ,(* length 1.5) ,(+ hcorr (* hpos bdist)))
        (moveto 0 -1)
        (curveto
         ,length -1
         ,(* length 0.5) ,(+ hcorr (* hpos bdist) -1)
         ,(* length 1.5) ,(+ hcorr (* hpos bdist) -1))
        (moveto 0 -2)
        (curveto
         ,length -2
         ,(* length 0.5) ,(+ hcorr (* hpos bdist) -2)
         ,(* length 1.5) ,(+ hcorr (* hpos bdist) -2)))))))


% Make a twisted staff.
#(define-markup-command
   (twist-staff layout props
                length hcorr hpos bdist)
   (number? number? number? number?)
   "Draw a 'twisted' curved staff with length LENGTH.

Starting from a point stencil, the height must be adjusted manually;
HCORR specifies the height correction, HPOS the height position, and
BDIST corresponds to the 'basic-distance' value of the
'staff-staff-spacing' property."
   (interpret-markup
    layout props
    (markup
     (#:path
      0.1
      `((moveto 0 -2)
        (curveto
         ,length -2
         ,(* length 0.5) ,(+ hcorr (* hpos bdist) 2)
         ,(* length 1.5) ,(+ hcorr (* hpos bdist) 2))
        (moveto 0 -1)
        (curveto
         ,length -1
         ,(* length 0.5) ,(+ hcorr (* hpos bdist) 1)
         ,(* length 1.5) ,(+ hcorr (* hpos bdist) 1))
        (moveto 0 0)
        (curveto
         ,length 0
         ,(* length 0.5) ,(+ hcorr (* hpos bdist))
         ,(* length 1.5) ,(+ hcorr (* hpos bdist)))
        (moveto 0 1)
        (curveto
         ,length 1
         ,(* length 0.5) ,(+ hcorr (* hpos bdist) -1)
         ,(* length 1.5) ,(+ hcorr (* hpos bdist) -1))
        (moveto 0 2)
        (curveto
         ,length 2
         ,(* length 0.5) ,(+ hcorr (* hpos bdist) -2)
         ,(* length 1.5) ,(+ hcorr (* hpos bdist) -2)))))))


% Cross staff
% -----------
%
% We abuse glissando lines as staff lines to get the desired effect.

fagott = \relative c {
  \set Staff.instrumentName = "Fagott"
  \clef bass
  c4 e g e

  \cadenzaOn
  \hideNotes
  \once\override Glissando.bound-details.left.padding = #0
  \once\override Glissando.bound-details.right.padding = #0
  \once\override NoteColumn.X-offset = #1.0
  <g, b d f a>8 \glissando
  \stopStaff
  s1
  \change Staff = "unten"
  \startStaff
  \once\override NoteColumn.X-offset = #-0.5
  <g b d f a>8
  \cadenzaOff
  \unHideNotes

  c4 e g e
}

blech = \relative c'' {
  \set Staff.instrumentName = "Blech"
  c1

  \cadenzaOn
  \hideNotes
  s8 c4 c c c s8
  \cadenzaOff
  \unHideNotes

  c1
}

pauke = \relative c {
  \set Staff.instrumentName = "Pauke"
  \clef bass
  c4 g c g

  \cadenzaOn
  \hideNotes
  \once\override Glissando.bound-details.left.padding = #0
  \once\override Glissando.bound-details.right.padding = #0
  \once\override NoteColumn.X-offset = #1.0
  <g b d f a>8 \glissando
  \stopStaff
  s1
  \change Staff = "oben"
  \startStaff
  \once\override NoteColumn.X-offset = #-0.5
  <g b d f a>8
  \cadenzaOff
  \unHideNotes

  c4 g c g
}

\markup\italic "Cross staff:"
<<
  \new Staff = "oben" \fagott
  \new Staff = "mitte" \blech
  \new Staff = "unten" \pauke
>>


% Chicane staff
% -------------
%
% We temporarily override the `BarLine` stencil to use
% `\chicane-staff`.  The drawing gets triggered by `\bar ""`.

fagott-bis = \relative c {
  \set Staff.instrumentName = "Fagott"
  \clef bass
  c4 e g e

  \cadenzaOn
  \hideNotes c8
  \bar ""
  \once \override Staff.BarLine.stencil =
    #(lambda (grob)
       (ly:stencil-combine-at-edge
        (ly:bar-line::print grob)
        X LEFT
        (grob-interpret-markup grob #{
          \markup \with-dimensions #'(0 . 0) #'(0 . 0)
            \concat {
              \hspace #-.1
              \chicane-staff #10.2 #0 #10 #-1.8
              \hspace #-.3
            } #} )
        -1.3))
  \stopStaff s1 \startStaff
  c8 \unHideNotes
  \change Staff = "unten"
  \cadenzaOff

  c4 e g e
}

blech-bis = \relative c'' {
  \set Staff.instrumentName = "Blech"
  c1

  \cadenzaOn
  s8 \hideNotes
  c4 c c c
  \unHideNotes s8
  \cadenzaOff

  c1
}

pauke-bis = \relative c {
  \set Staff.instrumentName = "Pauke"
  \clef bass
  c4 g c g

  \cadenzaOn
  \hideNotes c8
  \bar ""
  \once \override Staff.BarLine.stencil =
    #(lambda (grob)
       (ly:stencil-combine-at-edge
        (ly:bar-line::print grob)
        X LEFT
        (grob-interpret-markup grob #{
          \markup \with-dimensions #'(0 . 0) #'(0 . 0)
          \concat {
            \hspace #-.1
            \chicane-staff #10.2 #0 #10 #1.8
            \hspace #-.3
          } #} )
        -1.3))
  \stopStaff s1 \startStaff
  c8 \unHideNotes
  \change Staff = "oben"
  \cadenzaOff

  c4 g c g
}

\markup\italic "Chicane staff:"
<<
  \new Staff = "oben" \fagott-bis
  \new Staff = "mitte" \blech-bis
  \new Staff = "unten" \pauke-bis
>>


% Twisted staff
% -------------
%
% We temporarily override the `BarLine` stencil to use
% `\twist-staff`.  The drawing gets triggered by `\bar ""`.

fagott-ter = \relative c {
  \set Staff.instrumentName = "Fagott"
  \clef bass
  c4 e g e

  \cadenzaOn
  \hideNotes c8
  \bar ""
  \once \override Staff.BarLine.stencil =
    #(lambda (grob)
       (ly:stencil-combine-at-edge
        (ly:bar-line::print grob)
        X LEFT
        (grob-interpret-markup grob #{
          \markup \with-dimensions #'(0 . 0) #'(0 . 0)
          \concat {
            \hspace #-.1
            \twist-staff #10.2 #0 #10 #-1.8
            \hspace #-.3
          } #} )
        -1.3))
  \stopStaff s1 \startStaff
  c8 \unHideNotes
  \change Staff = "unten"
  \cadenzaOff

  c4 e g e
}

blech-ter = \relative c'' {
  \set Staff.instrumentName = "Blech"
  c1

  \cadenzaOn
  s8 \hideNotes
  c4 c c c
  \unHideNotes s8
  \cadenzaOff

  c1
}

pauke-ter = \relative c {
  \set Staff.instrumentName = "Pauke"
  \clef bass
  c4 g c g

  \cadenzaOn
  \hideNotes c8
  \bar ""
  \once \override Staff.BarLine.stencil =
    #(lambda (grob)
       (ly:stencil-combine-at-edge
        (ly:bar-line::print grob)
        X LEFT
        (grob-interpret-markup grob #{
          \markup \with-dimensions #'(0 . 0) #'(0 . 0)
          \concat {
            \hspace #-.1
            \twist-staff #10.2 #0 #10 #1.8
            \hspace #-.3
          } #} )
        -1.3))
  \stopStaff s1 \startStaff
  c8 \unHideNotes
  \change Staff = "oben"
  \cadenzaOff

  c4 g c g
}

\markup\italic "Twisted staff:"
\score {
  <<
    \new Staff = "oben" \fagott-ter
    \new Staff = "mitte" \blech-ter
    \new Staff = "unten" \pauke-ter
  >>
}

\paper { tagline = ##f }