Thank you David for this example. I agree with Aaron that ossia notes should be first when the ossia measure goes above the music. That way you have a similar "feeling" of the \relative effect as when using << { %abovemusic} \\ {%belowmusic} >>. However, I went ahead, and, for the sake of completeness, split Aaron's code into two functions, namely \ossiaAbove and \ossiaBelow, because both options should be available (writing f. ex. ossia measures for the left hand of the piano is usually done below the staff). The below ossia poses the question "should notes be written first or after?". By analogy to the << {} \\ {} >> construction, I think they should be written after, since they're some sort of "below" or "second" voice. In that case, as David suggests, an independent \relative block should always be used:
\version "2.20.0"
\layout {
\context {
\Staff
\name OssiaStaff
\alias Staff
\remove "Time_signature_engraver"
\magnifyStaff #2/3
%\hide Clef
%firstClef = ##f
instrumentName = "ossia"
shortInstrumentName = "ossia"
}
\inherit-acceptability OssiaStaff Staff
}
ossiaAbove =
#(define-music-function
(ossia-music music)
(ly:music? ly:music?)
(let ((staff-name #f)
(clef-props '(clefGlyph
middleCClefPosition
clefPosition
clefTransposition
clefTranspositionStyle)))
(define (initialize context)
(set! staff-name
(ly:context-id (ly:context-find context 'Staff)))
(set! clef-props
(map (lambda (prop)
(cons prop (ly:context-property context prop)))
clef-props)))
(define (update context)
(ly:context-set-property! context
'alignAboveContext staff-name)
(for-each (lambda (prop)
(ly:context-set-property! context
(car prop) (cdr prop)))
clef-props)
(ly:set-middle-C! context))
#{ \applyContext #initialize
<< \new OssiaStaff
\with #(ly:make-context-mod `((apply ,update)))
{ #ossia-music }
#music >> #}))
ossiaBelow =
#(define-music-function
(ossia-music music)
(ly:music? ly:music?)
(let ((staff-name #f)
(clef-props '(clefGlyph
middleCClefPosition
clefPosition
clefTransposition
clefTranspositionStyle)))
(define (initialize context)
(set! staff-name
(ly:context-id (ly:context-find context 'Staff)))
(set! clef-props
(map (lambda (prop)
(cons prop (ly:context-property context prop)))
clef-props)))
(define (update context)
(ly:context-set-property! context
'alignBelowContext staff-name)
(for-each (lambda (prop)
(ly:context-set-property! context
(car prop) (cdr prop)))
clef-props)
(ly:set-middle-C! context))
#{ \applyContext #initialize
<< \new OssiaStaff
\with #(ly:make-context-mod `((apply ,update)))
{ #music }
#ossia-music >> #}))
<<
\new StaffGroup \with {
\override SystemStartBracket.stencil = ##f
\override SpanBar.glyph-name = #"!"
}
<<
\new Staff = "violin"
\relative {
c'4 d e g
f d e g
f d e g
\time 3/4
c b c
\time 4/4
\ossiaAbove {c b c2 } {e4 f g2}
}
>>
\new StaffGroup \with {
\override SystemStartBracket.stencil = ##f
\override SpanBar.glyph-name = #"!"
} <<
\new Staff = "viola"
\relative {
\clef alto
c'4 d e g
f d e g
f d e g
\time 3/4
\ossiaBelow { e d f }
\relative { c' b c }
\time 4/4
c b c2
}
>> >>
I'd love to see these functions together with the new OssiaStaff context incorporated into Lilypond by default. Doing so wouldn't only provide a syntax for ossias and a useful new context but would also bring the necessary attention that the respective part in the manual is currently in need of.
Best regards,
Martín.