5

In german the english note name B is named H (while english Bb is named B)

The german note name H can be entered when using \language "deutsch". But when using \easyHeadsOn the

\language "deutsch"
{ \easyHeadsOn h2 }

I'd expect the letter H to be shown in the head. But instead the english letter B is shown.

\set printNotesLanguage = "deutsch" seems to have no effect.

\language "deutsch"
melody = {
  \easyHeadsOn h'2
}

<<
  \new Staff { \key c \major \melody }
  \new NoteNames { \set printNotesLanguage = "deutsch" \melody }
>>

enter image description here

1 Answer 1

3

\easyHeadsOn uses the NoteHead.note-names property for the displayed names. If not specified it directly translates the pitch class using ASCII rather than using the localized note-names->string. So you may do

\language "deutsch"
melody = {
  \override NoteHead.note-names = ##("c" "d" "e" "f" "g" "a" "h")
  \easyHeadsOn h'2
}

<<
  \new Staff { \key c \major \melody }
  \new NoteNames { \set printNotesLanguage = "deutsch" \melody }
>>

or alternatively make the whole thing localized:

#(define-public (note-head::brew-ez-stencil grob)
  (let* ((log (ly:grob-property grob 'duration-log))
         (pitch (ly:event-property (event-cause grob) 'pitch))
         (pitch-index (ly:pitch-notename pitch))
         (note-names (ly:grob-property grob 'note-names))
         (pitch-string (if (and (vector? note-names)
                                (> (vector-length note-names) pitch-index))
                           (vector-ref note-names pitch-index)
                           ((@@ (lily) note-name->string) pitch)))
         (staff-space (ly:staff-symbol-staff-space grob))
         (line-thickness (ly:staff-symbol-line-thickness grob))
         (stem (ly:grob-object grob 'stem #f))
         (stem-thickness (* (if stem
                                (ly:grob-property stem 'thickness)
                                1.3)
                            line-thickness))
         (font-size (ly:grob-property grob 'font-size 0))
         (radius (* (magstep font-size) (/ (+ staff-space line-thickness) 2)))
         (letter (make-fontsize-markup
                  -8
                  (make-center-align-markup (make-vcenter-markup pitch-string))))
         (filled-circle (make-draw-circle-markup radius 0 #t)))

    (ly:stencil-translate-axis
     (grob-interpret-markup
      grob
      (if (>= log 2)
          (make-combine-markup
           filled-circle
           (make-with-color-markup white letter))
          (make-combine-markup
           (make-combine-markup
            filled-circle
            (make-with-color-markup white (make-draw-circle-markup
                                           (- radius stem-thickness) 0 #t)))
           letter)))
     radius X)))

easyHeadsOn = {
  \override NoteHead.stencil = #note-head::brew-ez-stencil
  \override NoteHead.font-family = #'sans
  \override NoteHead.font-series = #'bold
}


\language "italiano"
melody = {
  \easyHeadsOn si'2
}

<<
  \new Staff { \key do \major \melody }
  \new NoteNames { \melody }
>>

EDIT: A version that allows differentiation between h and b:

#(define (note-head::brew-ez-stencil grob)
   (let* ((log (ly:grob-property grob 'duration-log))
          (pitch-string (ly:grob-property grob 'text))
          (staff-space (ly:staff-symbol-staff-space grob))
          (line-thickness (ly:staff-symbol-line-thickness grob))
          (stem (ly:grob-object grob 'stem #f))
          (stem-thickness (* (if stem
                                 (ly:grob-property stem 'thickness)
                                 1.3)
                             line-thickness))
          (font-size (ly:grob-property grob 'font-size 0))
          (radius (* (magstep font-size) (/ (+ staff-space line-thickness) 2)))
          (letter (make-fontsize-markup
                   -8
                   (make-center-align-markup (make-vcenter-markup pitch-string))))
          (filled-circle (make-draw-circle-markup radius 0 #t)))

     (ly:stencil-translate-axis
      (grob-interpret-markup
       grob
       (if (>= log 2)
           (make-combine-markup
            filled-circle
            (make-with-color-markup white letter))
           (make-combine-markup
            (make-combine-markup
             filled-circle
             (make-with-color-markup white (make-draw-circle-markup
                                            (- radius stem-thickness) 0 #t)))
            letter)))
      radius X)))

#(define (note-head::brew-ez-text grob)
   (let* ((pitch (ly:event-property (event-cause grob) 'pitch))
          (pitch-index (ly:pitch-notename pitch))
          (note-names (ly:grob-property grob 'note-names))
          (pitch-string (if (and (vector? note-names)
                                 (> (vector-length note-names) pitch-index))
                            (vector-ref note-names pitch-index)
                            (string
                             (integer->char
                              (+ (modulo (+ pitch-index 2) 7)
                                 (char->integer #\A)))))))
      pitch-string))

#(define (note-head::brew-ez-text-loc grob)
   (let* ((pitch (ly:event-property (event-cause grob) 'pitch))
         (pitch-index (ly:pitch-notename pitch))
         (note-names (ly:grob-property grob 'note-names))
         (pitch-string (if (and (vector? note-names)
                                (> (vector-length note-names) pitch-index))
                           (vector-ref note-names pitch-index)
                           ((@@ (lily) note-name->string) pitch))))
     pitch-string))

#(define ((note-name->german-string B-instead-of-Bb)
          pitch lowercase?)
   (let* ((name (ly:pitch-notename pitch))
          (alt-semitones ((@@ (lily) pitch-alteration-semitones) pitch))
          (n-a (if (member (cons name alt-semitones) `((6 . -1) (6 . -2)))
                   (cons 7 (+ (if B-instead-of-Bb 1 0) alt-semitones))
                   (cons name alt-semitones))))
     ((@@ (lily) conditional-string-capitalize)
      (vector-ref #("c" "d" "e" "f" "g" "a" "h" "b") (car n-a))
      lowercase?)))

#(define (note-head::brew-ez-text-german grob)
   (let* ((pitch (ly:event-property (event-cause grob) 'pitch))
          (pitch-index (ly:pitch-notename pitch))
          (note-names (ly:grob-property grob 'note-names))
          (pitch-string (if (and (vector? note-names)
                                 (> (vector-length note-names) pitch-index))
                            (vector-ref note-names pitch-index)
                            ((note-name->german-string #t) pitch #t))))
      pitch-string))

easyHeadsOn = {
  \override NoteHead.stencil = #note-head::brew-ez-stencil
  \override NoteHead.text = #note-head::brew-ez-text
  \override NoteHead.font-family = #'sans
  \override NoteHead.font-series = #'bold
}


\language "deutsch"
melody = {
  \easyHeadsOn
  h'2 b'
  \override NoteHead.text = #note-head::brew-ez-text-loc
  h'2 b'
  \override NoteHead.text = #note-head::brew-ez-text-german
  h'2 b'
}

<<
  \new Staff { \key c \major \melody }
  \new NoteNames { \melody }
>>

(this version makes the text come from the NoteHead.text property).

9
  • The first method shows h-flat where it should have b. Aug 7, 2023 at 12:48
  • With the Lisp method get an error: filename.ly:12:16: Wrong number of arguments to #<primitive-procedure ly:grob-object>
    – wolfrevo
    Aug 7, 2023 at 13:59
  • 1
    @wolfrevo What Lilypond version are you on? I suppose this is due to the optional default to ly:grob-object, which has been added mid 2021, which should have been around 2.23.3. Of course you can always adapt the function from your local version.
    – Lazy
    Aug 7, 2023 at 14:52
  • 2
    @ElementsinSpace Added a version for b.
    – Lazy
    Aug 7, 2023 at 15:12
  • 1
    @wolfrevo For the notenames you could do \set noteNameFunction = #(lambda (pitch ctx) (note-name->german-markup pitch #t))
    – Lazy
    Aug 7, 2023 at 23:42

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.