Re: Align above "current" staff

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Martín Rincón Botero
I hope this message lands in the right 2018 thread. I find an ossia function very worth the work! I tried several things yesterday but none of them really worked. I amended a few details to Urs/David's code (a couple of \with attributes) but there are still some minor issues (other than this big 13 years old bug https://gitlab.com/lilypond/lilypond/-/issues/127).

When I look at the code (see below) I would expect this to happen: \ossia {%ossiamusic} {%music}. What happens is the opposite. This is trivial, since the only thing you have to tell the user is that the normal music goes before the ossia music, but it makes me wonder why anyways... Other minor issues are that the ossia music doesn't inherit the clef from the normal music, and that placing all this inside a \relative is not reliable (the first note of whichever of both components might be in an unexpected octave). Does Urs, who started working on this, or David (or anyone :-)) have any idea on how to solve these minor issues? Here the amended code with an example that demonstrate them:

ossia =
#(define-music-function
  (music ossia-music) (ly:music? ly:music?)
  (let ((name "initialized"))
    #{
      \applyContext
      #(lambda (context)
         (set! name (ly:context-id (ly:context-find context 'Staff)))
         )

      << \new Staff \with {
        #(ly:make-context-mod
          `((apply ,(lambda (c)
                       (set! (ly:context-property c 'alignAboveContext) name)
                     ))))
     \remove "Time_signature_engraver"
    \magnifyStaff #2/3
    \hide Clef
    firstClef = ##f
         } { #ossia-music }
      #music
      >>
      % Create \new Staff with ossia-music
    #}))

\new Staff = "viola" \relative {
  \clef alto
  c'4 d e g
 \ossia {c^"c'?" b c d } { e^"Treble clef? I'm not a violin!" d f e }
 c b c2
}
image.png

Cheers,
Martín.
--
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Aaron Hill
On 2020-09-27 3:23 am, Martín Rincón Botero wrote:

> I hope this message lands in the right 2018 thread. I find an ossia
> function very worth the work! I tried several things yesterday but
> none of them really worked. I amended a few details to Urs/David's
> code (a couple of \with attributes) but there are still some minor
> issues (other than this big 13 years old bug
> https://gitlab.com/lilypond/lilypond/-/issues/127).
>
> When I look at the code (see below) I would expect this to happen:
> \ossia {%ossiamusic} {%music}. What happens is the opposite. This is
> trivial, since the only thing you have to tell the user is that the
> normal music goes before the ossia music, but it makes me wonder why
> anyways... Other minor issues are that the ossia music doesn't inherit
> the clef from the normal music, and that placing all this inside a
> \relative is not reliable (the first note of whichever of both
> components might be in an unexpected octave). Does Urs, who started
> working on this, or David (or anyone :-)) have any idea on how to
> solve these minor issues? Here the amended code with an example that
> demonstrate them:
>
> [ . . . ]
Firstly let me be clear that I have not chased down all information
relating to this thread, so I very well might be missing important
details.

I can see no reason why the order of arguments could not be swapped so
that the ossia-music comes first.  This is very useful as it clarifies
why \relative works the way it does.  The ossia-music expression gets
processed before the remaining music.  The first "c" in the remaining
music follows the final "e" in the ossia-music, not the "g" is the
preceding music.

Regarding clefs, I have a patched version of \ossia that attempts to
match the current clef settings by mimicking how \clef works:

%%%%
\version "2.20.0"

\layout {
   \context {
     \Staff
     \name OssiaStaff
     \alias Staff
     \remove "Time_signature_engraver"
     \magnifyStaff #2/3
     \hide Clef
     firstClef = ##f
   }
   \inherit-acceptability OssiaStaff Staff
}

ossia =
#(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 >> #}))

\new Staff = "viola" \relative {
   \clef alto
   c'4 d e g
   \ossia { e^"Treble clef? No, it's alto now." d f e }
          { c^"c'? Yes, because \\relative says so." b c d }
   c b c2
}
%%%%

Note that I went ahead and defined an OssiaStaff context so that
properties relating to it are not buried within the \ossia function.  
Also a little refactoring should make the function's logic a little
easier to follow.


-- Aaron Hill

ossia.cropped.png (24K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Martín Rincón Botero
Dear Aaron,

this is, as usual, excellent. Thank you very much! I was reading Elaine Gould's book regarding ossias and two things would improve this snippet: Naming the ossia staff "ossia" (adding instrumentName = "ossia" to \context {  \Staff ...} doesn't work) and joining both systems with dashed bar lines except for the first barline of the system (putting \new StaffGroup \with {  \override SpanBar.glyph-name = #"!"   \remove System_start_delimiter_engraver } before << \new OssiaStaff... >> doesn't work either). What am I missing?

Best regards,
Martín. 

Am So., 27. Sept. 2020 um 13:26 Uhr schrieb Aaron Hill <[hidden email]>:
On 2020-09-27 3:23 am, Martín Rincón Botero wrote:
> I hope this message lands in the right 2018 thread. I find an ossia
> function very worth the work! I tried several things yesterday but
> none of them really worked. I amended a few details to Urs/David's
> code (a couple of \with attributes) but there are still some minor
> issues (other than this big 13 years old bug
> https://gitlab.com/lilypond/lilypond/-/issues/127).
>
> When I look at the code (see below) I would expect this to happen:
> \ossia {%ossiamusic} {%music}. What happens is the opposite. This is
> trivial, since the only thing you have to tell the user is that the
> normal music goes before the ossia music, but it makes me wonder why
> anyways... Other minor issues are that the ossia music doesn't inherit
> the clef from the normal music, and that placing all this inside a
> \relative is not reliable (the first note of whichever of both
> components might be in an unexpected octave). Does Urs, who started
> working on this, or David (or anyone :-)) have any idea on how to
> solve these minor issues? Here the amended code with an example that
> demonstrate them:
>
> [ . . . ]

Firstly let me be clear that I have not chased down all information
relating to this thread, so I very well might be missing important
details.

I can see no reason why the order of arguments could not be swapped so
that the ossia-music comes first.  This is very useful as it clarifies
why \relative works the way it does.  The ossia-music expression gets
processed before the remaining music.  The first "c" in the remaining
music follows the final "e" in the ossia-music, not the "g" is the
preceding music.

Regarding clefs, I have a patched version of \ossia that attempts to
match the current clef settings by mimicking how \clef works:

%%%%
\version "2.20.0"

\layout {
   \context {
     \Staff
     \name OssiaStaff
     \alias Staff
     \remove "Time_signature_engraver"
     \magnifyStaff #2/3
     \hide Clef
     firstClef = ##f
   }
   \inherit-acceptability OssiaStaff Staff
}

ossia =
#(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 >> #}))

\new Staff = "viola" \relative {
   \clef alto
   c'4 d e g
   \ossia { e^"Treble clef? No, it's alto now." d f e }
          { c^"c'? Yes, because \\relative says so." b c d }
   c b c2
}
%%%%

Note that I went ahead and defined an OssiaStaff context so that
properties relating to it are not buried within the \ossia function. 
Also a little refactoring should make the function's logic a little
easier to follow.


-- Aaron Hill


--
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Martín Rincón Botero
Sorry, I wasn't paying attention. shortInstrumentName = "ossia" clearly works (instrumentName should work as well!).

Am So., 27. Sept. 2020 um 16:46 Uhr schrieb Martín Rincón Botero <[hidden email]>:
Dear Aaron,

this is, as usual, excellent. Thank you very much! I was reading Elaine Gould's book regarding ossias and two things would improve this snippet: Naming the ossia staff "ossia" (adding instrumentName = "ossia" to \context {  \Staff ...} doesn't work) and joining both systems with dashed bar lines except for the first barline of the system (putting \new StaffGroup \with {  \override SpanBar.glyph-name = #"!"   \remove System_start_delimiter_engraver } before << \new OssiaStaff... >> doesn't work either). What am I missing?

Best regards,
Martín. 

Am So., 27. Sept. 2020 um 13:26 Uhr schrieb Aaron Hill <[hidden email]>:
On 2020-09-27 3:23 am, Martín Rincón Botero wrote:
> I hope this message lands in the right 2018 thread. I find an ossia
> function very worth the work! I tried several things yesterday but
> none of them really worked. I amended a few details to Urs/David's
> code (a couple of \with attributes) but there are still some minor
> issues (other than this big 13 years old bug
> https://gitlab.com/lilypond/lilypond/-/issues/127).
>
> When I look at the code (see below) I would expect this to happen:
> \ossia {%ossiamusic} {%music}. What happens is the opposite. This is
> trivial, since the only thing you have to tell the user is that the
> normal music goes before the ossia music, but it makes me wonder why
> anyways... Other minor issues are that the ossia music doesn't inherit
> the clef from the normal music, and that placing all this inside a
> \relative is not reliable (the first note of whichever of both
> components might be in an unexpected octave). Does Urs, who started
> working on this, or David (or anyone :-)) have any idea on how to
> solve these minor issues? Here the amended code with an example that
> demonstrate them:
>
> [ . . . ]

Firstly let me be clear that I have not chased down all information
relating to this thread, so I very well might be missing important
details.

I can see no reason why the order of arguments could not be swapped so
that the ossia-music comes first.  This is very useful as it clarifies
why \relative works the way it does.  The ossia-music expression gets
processed before the remaining music.  The first "c" in the remaining
music follows the final "e" in the ossia-music, not the "g" is the
preceding music.

Regarding clefs, I have a patched version of \ossia that attempts to
match the current clef settings by mimicking how \clef works:

%%%%
\version "2.20.0"

\layout {
   \context {
     \Staff
     \name OssiaStaff
     \alias Staff
     \remove "Time_signature_engraver"
     \magnifyStaff #2/3
     \hide Clef
     firstClef = ##f
   }
   \inherit-acceptability OssiaStaff Staff
}

ossia =
#(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 >> #}))

\new Staff = "viola" \relative {
   \clef alto
   c'4 d e g
   \ossia { e^"Treble clef? No, it's alto now." d f e }
          { c^"c'? Yes, because \\relative says so." b c d }
   c b c2
}
%%%%

Note that I went ahead and defined an OssiaStaff context so that
properties relating to it are not buried within the \ossia function. 
Also a little refactoring should make the function's logic a little
easier to follow.


-- Aaron Hill


--


--
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Martín Rincón Botero
I wasn't paying enough attention either for the dashed bar lines connecting both staves. If this could be made to work into the function itself would be great, but I suppose it's quite difficult if not impossible since Lilypond has to be aware of the Staffgroup first, before even engraving the ossia measure, right?

\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
}

ossia =
#(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 >> #}))

  <<
  \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
   c b c2
}

\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
   \ossia { e^"Treble clef? No, it's alto now." d f  }
          { c^"c'? Yes, because \\relative says so." b c  }
   \time 4/4
   c b c2
}

  >> >>

image.png


Cheers,
Martín.

Am So., 27. Sept. 2020 um 16:50 Uhr schrieb Martín Rincón Botero <[hidden email]>:
Sorry, I wasn't paying attention. shortInstrumentName = "ossia" clearly works (instrumentName should work as well!).

Am So., 27. Sept. 2020 um 16:46 Uhr schrieb Martín Rincón Botero <[hidden email]>:
Dear Aaron,

this is, as usual, excellent. Thank you very much! I was reading Elaine Gould's book regarding ossias and two things would improve this snippet: Naming the ossia staff "ossia" (adding instrumentName = "ossia" to \context {  \Staff ...} doesn't work) and joining both systems with dashed bar lines except for the first barline of the system (putting \new StaffGroup \with {  \override SpanBar.glyph-name = #"!"   \remove System_start_delimiter_engraver } before << \new OssiaStaff... >> doesn't work either). What am I missing?

Best regards,
Martín. 

Am So., 27. Sept. 2020 um 13:26 Uhr schrieb Aaron Hill <[hidden email]>:
On 2020-09-27 3:23 am, Martín Rincón Botero wrote:
> I hope this message lands in the right 2018 thread. I find an ossia
> function very worth the work! I tried several things yesterday but
> none of them really worked. I amended a few details to Urs/David's
> code (a couple of \with attributes) but there are still some minor
> issues (other than this big 13 years old bug
> https://gitlab.com/lilypond/lilypond/-/issues/127).
>
> When I look at the code (see below) I would expect this to happen:
> \ossia {%ossiamusic} {%music}. What happens is the opposite. This is
> trivial, since the only thing you have to tell the user is that the
> normal music goes before the ossia music, but it makes me wonder why
> anyways... Other minor issues are that the ossia music doesn't inherit
> the clef from the normal music, and that placing all this inside a
> \relative is not reliable (the first note of whichever of both
> components might be in an unexpected octave). Does Urs, who started
> working on this, or David (or anyone :-)) have any idea on how to
> solve these minor issues? Here the amended code with an example that
> demonstrate them:
>
> [ . . . ]

Firstly let me be clear that I have not chased down all information
relating to this thread, so I very well might be missing important
details.

I can see no reason why the order of arguments could not be swapped so
that the ossia-music comes first.  This is very useful as it clarifies
why \relative works the way it does.  The ossia-music expression gets
processed before the remaining music.  The first "c" in the remaining
music follows the final "e" in the ossia-music, not the "g" is the
preceding music.

Regarding clefs, I have a patched version of \ossia that attempts to
match the current clef settings by mimicking how \clef works:

%%%%
\version "2.20.0"

\layout {
   \context {
     \Staff
     \name OssiaStaff
     \alias Staff
     \remove "Time_signature_engraver"
     \magnifyStaff #2/3
     \hide Clef
     firstClef = ##f
   }
   \inherit-acceptability OssiaStaff Staff
}

ossia =
#(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 >> #}))

\new Staff = "viola" \relative {
   \clef alto
   c'4 d e g
   \ossia { e^"Treble clef? No, it's alto now." d f e }
          { c^"c'? Yes, because \\relative says so." b c d }
   c b c2
}
%%%%

Note that I went ahead and defined an OssiaStaff context so that
properties relating to it are not buried within the \ossia function. 
Also a little refactoring should make the function's logic a little
easier to follow.


-- Aaron Hill


--


--


--
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Martín Rincón Botero
I said
"If this could be made to work into the function itself would be great"

Thinking twice, I guess the user should have the freedom to make an ossia that's not connected to the main staff. My problem has been solved then! :-) What does Urs think of this?

Am So., 27. Sept. 2020 um 17:02 Uhr schrieb Martín Rincón Botero <[hidden email]>:
I wasn't paying enough attention either for the dashed bar lines connecting both staves. If this could be made to work into the function itself would be great, but I suppose it's quite difficult if not impossible since Lilypond has to be aware of the Staffgroup first, before even engraving the ossia measure, right?

\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
}

ossia =
#(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 >> #}))

  <<
  \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
   c b c2
}

\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
   \ossia { e^"Treble clef? No, it's alto now." d f  }
          { c^"c'? Yes, because \\relative says so." b c  }
   \time 4/4
   c b c2
}

  >> >>

image.png


Cheers,
Martín.

Am So., 27. Sept. 2020 um 16:50 Uhr schrieb Martín Rincón Botero <[hidden email]>:
Sorry, I wasn't paying attention. shortInstrumentName = "ossia" clearly works (instrumentName should work as well!).

Am So., 27. Sept. 2020 um 16:46 Uhr schrieb Martín Rincón Botero <[hidden email]>:
Dear Aaron,

this is, as usual, excellent. Thank you very much! I was reading Elaine Gould's book regarding ossias and two things would improve this snippet: Naming the ossia staff "ossia" (adding instrumentName = "ossia" to \context {  \Staff ...} doesn't work) and joining both systems with dashed bar lines except for the first barline of the system (putting \new StaffGroup \with {  \override SpanBar.glyph-name = #"!"   \remove System_start_delimiter_engraver } before << \new OssiaStaff... >> doesn't work either). What am I missing?

Best regards,
Martín. 

Am So., 27. Sept. 2020 um 13:26 Uhr schrieb Aaron Hill <[hidden email]>:
On 2020-09-27 3:23 am, Martín Rincón Botero wrote:
> I hope this message lands in the right 2018 thread. I find an ossia
> function very worth the work! I tried several things yesterday but
> none of them really worked. I amended a few details to Urs/David's
> code (a couple of \with attributes) but there are still some minor
> issues (other than this big 13 years old bug
> https://gitlab.com/lilypond/lilypond/-/issues/127).
>
> When I look at the code (see below) I would expect this to happen:
> \ossia {%ossiamusic} {%music}. What happens is the opposite. This is
> trivial, since the only thing you have to tell the user is that the
> normal music goes before the ossia music, but it makes me wonder why
> anyways... Other minor issues are that the ossia music doesn't inherit
> the clef from the normal music, and that placing all this inside a
> \relative is not reliable (the first note of whichever of both
> components might be in an unexpected octave). Does Urs, who started
> working on this, or David (or anyone :-)) have any idea on how to
> solve these minor issues? Here the amended code with an example that
> demonstrate them:
>
> [ . . . ]

Firstly let me be clear that I have not chased down all information
relating to this thread, so I very well might be missing important
details.

I can see no reason why the order of arguments could not be swapped so
that the ossia-music comes first.  This is very useful as it clarifies
why \relative works the way it does.  The ossia-music expression gets
processed before the remaining music.  The first "c" in the remaining
music follows the final "e" in the ossia-music, not the "g" is the
preceding music.

Regarding clefs, I have a patched version of \ossia that attempts to
match the current clef settings by mimicking how \clef works:

%%%%
\version "2.20.0"

\layout {
   \context {
     \Staff
     \name OssiaStaff
     \alias Staff
     \remove "Time_signature_engraver"
     \magnifyStaff #2/3
     \hide Clef
     firstClef = ##f
   }
   \inherit-acceptability OssiaStaff Staff
}

ossia =
#(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 >> #}))

\new Staff = "viola" \relative {
   \clef alto
   c'4 d e g
   \ossia { e^"Treble clef? No, it's alto now." d f e }
          { c^"c'? Yes, because \\relative says so." b c d }
   c b c2
}
%%%%

Note that I went ahead and defined an OssiaStaff context so that
properties relating to it are not buried within the \ossia function. 
Also a little refactoring should make the function's logic a little
easier to follow.


-- Aaron Hill


--


--


--


--
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

David Wright
In reply to this post by Aaron Hill
On Sun 27 Sep 2020 at 04:25:21 (-0700), Aaron Hill wrote:
> On 2020-09-27 3:23 am, Martín Rincón Botero wrote:

> > When I look at the code (see below) I would expect this to happen:
> > \ossia {%ossiamusic} {%music}. What happens is the opposite. This is
> > trivial, since the only thing you have to tell the user is that the
> > normal music goes before the ossia music, but it makes me wonder why
> > […] Other minor issues are […] that placing all this inside a
> > \relative is not reliable (the first note of whichever of both
> > components might be in an unexpected octave). Does Urs, who started
> > working on this, or David (or anyone :-)) have any idea on how to
> > solve these minor issues? Here the amended code with an example that
> > demonstrate them:

> I can see no reason why the order of arguments could not be swapped so
> that the ossia-music comes first.  This is very useful as it clarifies
> why \relative works the way it does.  The ossia-music expression gets
> processed before the remaining music.  The first "c" in the remaining
> music follows the final "e" in the ossia-music, not the "g" is the
> preceding music.

I'm not sure that it does produce clarity (as opposed to merely
explaining the unreliability in perception). Would it not be
clearer to put the ossia music inside a \relative{}, so that
the main sequence of pitches carries through undisturbed, and
the ossia has its correct octave specified within itself, locally.

I always think it rather risky to put structure inside \relative{},
rather than putting the \relative{}s inside the structure.

In the attached, I have omitted any clefs so that notes can be
read more simply, and chosen the notes so that the octavation
of each segment is more obvious.

Cheers,
David.

botero.ly (913 bytes) Download Attachment
botero.pdf (42K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Aaron Hill
On 2020-09-27 7:35 pm, David Wright wrote:
> I'm not sure that it does produce clarity (as opposed to merely
> explaining the unreliability in perception). Would it not be
> clearer to put the ossia music inside a \relative{}, so that
> the main sequence of pitches carries through undisturbed, and
> the ossia has its correct octave specified within itself, locally.
>
> I always think it rather risky to put structure inside \relative{},
> rather than putting the \relative{}s inside the structure.

\relative is nothing more than a tool for a job.  Providing one
understands how it works and can manage the sequencing of notes, it is
not wrong nor unreliable to use at a top-level.  If it were either, then
LilyPond should not accept such usage.

The original \ossia function flips the arguments so the ordering of
notes behind the scenes as \relative sees them no longer matches the
natural progression within the input file.  As such, argument order
matters to accommodate folks who choose to use \relative at the higher
level and maintain consistency with the existing precedent that parallel
sections of music are processed in the order they occur within the
source:

%%%%
\relative { 1st 2nd << { 3rd 4th } \\ { 5th 6th } >> 7th 8th }
%%%%

With the original \ossia function, one must follow this sequencing:

%%%%
\relative { 1st 2nd \ossia { 5th(!) 6th } { 3rd(!) 4th } 7th(!) 8th }
%%%%

That is three times the natural ordering is disturbed, so fixing the
argument order definitely adds clarity.

Mind you, a user is always free to use \relative in a more localized
scope:

%%%%
{
   \relative { 1st 2nd }
   \ossia \relative { 1st 2nd }
          \relative { 1st 2nd }
   \relative { 1st 2nd }
}
%%%%

But surely the music argument *nearest* the \ossia command should be the
notes in the ossia itself, regardless of ones preference on using
\relative.  The alternative seems madness:

%%%%
{
   music preceding
   \ossia { careful, these are not the notes for the ossia }
          { here, written *below* those notes in the source,
            are the notes that will appear *above* them. }
   music following
}
%%%%


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Martín Rincón Botero
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
}
  >> >>

image.png


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.


Am Mo., 28. Sept. 2020 um 08:33 Uhr schrieb Aaron Hill <[hidden email]>:
On 2020-09-27 7:35 pm, David Wright wrote:
> I'm not sure that it does produce clarity (as opposed to merely
> explaining the unreliability in perception). Would it not be
> clearer to put the ossia music inside a \relative{}, so that
> the main sequence of pitches carries through undisturbed, and
> the ossia has its correct octave specified within itself, locally.
>
> I always think it rather risky to put structure inside \relative{},
> rather than putting the \relative{}s inside the structure.

\relative is nothing more than a tool for a job.  Providing one
understands how it works and can manage the sequencing of notes, it is
not wrong nor unreliable to use at a top-level.  If it were either, then
LilyPond should not accept such usage.

The original \ossia function flips the arguments so the ordering of
notes behind the scenes as \relative sees them no longer matches the
natural progression within the input file.  As such, argument order
matters to accommodate folks who choose to use \relative at the higher
level and maintain consistency with the existing precedent that parallel
sections of music are processed in the order they occur within the
source:

%%%%
\relative { 1st 2nd << { 3rd 4th } \\ { 5th 6th } >> 7th 8th }
%%%%

With the original \ossia function, one must follow this sequencing:

%%%%
\relative { 1st 2nd \ossia { 5th(!) 6th } { 3rd(!) 4th } 7th(!) 8th }
%%%%

That is three times the natural ordering is disturbed, so fixing the
argument order definitely adds clarity.

Mind you, a user is always free to use \relative in a more localized
scope:

%%%%
{
   \relative { 1st 2nd }
   \ossia \relative { 1st 2nd }
          \relative { 1st 2nd }
   \relative { 1st 2nd }
}
%%%%

But surely the music argument *nearest* the \ossia command should be the
notes in the ossia itself, regardless of ones preference on using
\relative.  The alternative seems madness:

%%%%
{
   music preceding
   \ossia { careful, these are not the notes for the ossia }
          { here, written *below* those notes in the source,
            are the notes that will appear *above* them. }
   music following
}
%%%%


-- Aaron Hill



--
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

David Wright
In reply to this post by Aaron Hill
On Sun 27 Sep 2020 at 23:32:08 (-0700), Aaron Hill wrote:

> On 2020-09-27 7:35 pm, David Wright wrote:
> > I'm not sure that it does produce clarity (as opposed to merely
> > explaining the unreliability in perception). Would it not be
> > clearer to put the ossia music inside a \relative{}, so that
> > the main sequence of pitches carries through undisturbed, and
> > the ossia has its correct octave specified within itself, locally.
> >
> > I always think it rather risky to put structure inside \relative{},
> > rather than putting the \relative{}s inside the structure.
>
> \relative is nothing more than a tool for a job.  Providing one
> understands how it works and can manage the sequencing of notes, it is
> not wrong nor unreliable to use at a top-level.  If it were either,
> then LilyPond should not accept such usage.
I agree entirely:

I did not say it's wrong, but risky. Nor that it's unreliable
(AFAICT it's deterministic): I quoted the observation of the OP,
"placing all this inside a \relative is not reliable", which is
their perception.

That wasn't my point, which was that placing structure within
\relative{} sequences increases the burden of remembering
which structures can affect \relative's idea of note order,
and hence octavation. Add enough structure and the benefit of
\relative could be outweighed. Examples on this list abound,
the most common (IMHO) being provoked by tags. My understanding
(which could be flawed) is that some people here recommend never
using \relative on this account.

But my example was designed to ameliorate the problem, just by
enclosing the ossia phrase in its own \relative{}.

> The original \ossia function flips the arguments so the ordering of
> notes behind the scenes as \relative sees them no longer matches the
> natural progression within the input file.  As such, argument order
> matters to accommodate folks who choose to use \relative at the higher
> level and maintain consistency with the existing precedent that
> parallel sections of music are processed in the order they occur
> within the source:

[…]

> But surely the music argument *nearest* the \ossia command should be
> the notes in the ossia itself, regardless of ones preference on using
> \relative.  The alternative seems madness:

Yes, I'd agree that locality is of overriding importance for the
arguments in the call, and also that the function should respect the
note ordering so that \relative works in the expected manner. (The
implementation of that would be "way above my pay-grade".)

Actually, my post didn't express any opinion about ordering, and the
example was based on the Botero one merely because it was easier to
eliminate consideration of clefs too. The recommendation demonstrated
in the example was only to add a \relative to the ossia phrase, and
a further benefit can be illustrated by the attached, which shows
how relatively (!) easy it is to add or remove any number of ossias
if you use this construction.

Removing one is just a matter of commenting out its line (only one
line when used with your sensible ordering of arguments), and adding
one only requires the extra burden of putting { } round the main
sequence of notes covering the same time interval. The octavation of
the original remains undisturbed.

Of course, I would agree that:
  \ossia \relative { f''^"ossia" c g d } { a^"main" f d b }
looks much more tidy and hence understandable than:
  \ossia { a^"main" f d b } \relative { f''^"ossia" c g d }

Even if, as suggested later in the thread, you have ossia-above and
ossia-below, I don't think that should affect this ordering. Any
analogy with the << { } \\ { } >> construction is probably unwise,
as that's something which appears not always to be understood anyway.

Cheers,
David.

botero.ly (1K) Download Attachment
botero.pdf (42K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Align above "current" staff

Martín Rincón Botero
Even if, as suggested later in the thread, you have ossia-above and
ossia-below, I don't think that should affect this ordering. Any
analogy with the << { } \\ { } >> construction is probably unwise,
as that's something which appears not always to be understood anyway.

On a second thought, I agree. Ordering of arguments in this function seems to be of utmost importance, not only because of the \relative construction, but also because the function needs to appear first no matter what (I can't for example use {#music } \ossiaBelow {#ossia-music}). So it makes more sense to attach the notes that the function appears to contain on its side and not afterwards. For the sake of "discoverability" here the code again with #ossia-music back to where it belongs:

\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)))
             { #ossia-music }
          #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  }
      { c b c  }
   \time 4/4
   c b c2
}
  >> >>

By the way, the thread I was hoping to be replying to with my first message was this one http://lilypond.1069038.n5.nabble.com/Align-above-quot-current-quot-staff-td214624.html.

Cheers,
Martín.

Am Mo., 28. Sept. 2020 um 17:51 Uhr schrieb David Wright <[hidden email]>:
On Sun 27 Sep 2020 at 23:32:08 (-0700), Aaron Hill wrote:
> On 2020-09-27 7:35 pm, David Wright wrote:
> > I'm not sure that it does produce clarity (as opposed to merely
> > explaining the unreliability in perception). Would it not be
> > clearer to put the ossia music inside a \relative{}, so that
> > the main sequence of pitches carries through undisturbed, and
> > the ossia has its correct octave specified within itself, locally.
> >
> > I always think it rather risky to put structure inside \relative{},
> > rather than putting the \relative{}s inside the structure.
>
> \relative is nothing more than a tool for a job.  Providing one
> understands how it works and can manage the sequencing of notes, it is
> not wrong nor unreliable to use at a top-level.  If it were either,
> then LilyPond should not accept such usage.

I agree entirely:

I did not say it's wrong, but risky. Nor that it's unreliable
(AFAICT it's deterministic): I quoted the observation of the OP,
"placing all this inside a \relative is not reliable", which is
their perception.

That wasn't my point, which was that placing structure within
\relative{} sequences increases the burden of remembering
which structures can affect \relative's idea of note order,
and hence octavation. Add enough structure and the benefit of
\relative could be outweighed. Examples on this list abound,
the most common (IMHO) being provoked by tags. My understanding
(which could be flawed) is that some people here recommend never
using \relative on this account.

But my example was designed to ameliorate the problem, just by
enclosing the ossia phrase in its own \relative{}.

> The original \ossia function flips the arguments so the ordering of
> notes behind the scenes as \relative sees them no longer matches the
> natural progression within the input file.  As such, argument order
> matters to accommodate folks who choose to use \relative at the higher
> level and maintain consistency with the existing precedent that
> parallel sections of music are processed in the order they occur
> within the source:

[…]

> But surely the music argument *nearest* the \ossia command should be
> the notes in the ossia itself, regardless of ones preference on using
> \relative.  The alternative seems madness:

Yes, I'd agree that locality is of overriding importance for the
arguments in the call, and also that the function should respect the
note ordering so that \relative works in the expected manner. (The
implementation of that would be "way above my pay-grade".)

Actually, my post didn't express any opinion about ordering, and the
example was based on the Botero one merely because it was easier to
eliminate consideration of clefs too. The recommendation demonstrated
in the example was only to add a \relative to the ossia phrase, and
a further benefit can be illustrated by the attached, which shows
how relatively (!) easy it is to add or remove any number of ossias
if you use this construction.

Removing one is just a matter of commenting out its line (only one
line when used with your sensible ordering of arguments), and adding
one only requires the extra burden of putting { } round the main
sequence of notes covering the same time interval. The octavation of
the original remains undisturbed.

Of course, I would agree that:
  \ossia \relative { f''^"ossia" c g d } { a^"main" f d b }
looks much more tidy and hence understandable than:
  \ossia { a^"main" f d b } \relative { f''^"ossia" c g d }

Even if, as suggested later in the thread, you have ossia-above and
ossia-below, I don't think that should affect this ordering. Any
analogy with the << { } \\ { } >> construction is probably unwise,
as that's something which appears not always to be understood anyway.

Cheers,
David.


--