That's amazing Lukas! :chefkiss: Thanks so much. Drew On Wed, 29 Jan 2025 at 15:47, Lukas-Fabian Moser <l...@gmx.de> wrote:
> Hi Drew, > > ... which is great, since it means that the noteNameFunction gets called >> with the current context (as opposed to only a pitch), which means we can >> read the tonic from the context and do not need to write our own engraver >> (whose job it would be to read the context's tonic and pass it to our note >> NoteName grobs). The only caveat is that, by default, a NoteNames context >> doesn't \consist the Key_engraver, so it knows nothing about tonics. So we >> add this engraver, but then have to \omit the actual printed key signatures. >> > Here a new version (now only the NoteNames version) that allows specifying > the syllable to use for the tonic (as defined by \key): > > \version "2.25.21" > > #(set-object-property! 'tonicSyllable 'translation-type? string?) > > #(define (normalize-pitch p) > (ly:make-pitch 0 (ly:pitch-notename p) (ly:pitch-alteration p))) > > #(define (inv-assoc key alist default) > (let ((resulting-pair > (find (lambda (entry) > (equal? (cdr entry) > key)) > alist))) > (if resulting-pair > (car resulting-pair) > default))) > > #(define-markup-command (highlight-tonic layout props arg) (markup?) > (interpret-markup layout props > (markup #:bold #:with-color red arg))) > > extract-syllables = > #(define-scheme-function (unknown def) ((string? "?") ly:music?) > (map > (lambda (note-ev) > (cons > (normalize-pitch (ly:music-property note-ev 'pitch)) > (let ((text-script (extract-typed-music note-ev > 'text-script-event))) > (if (pair? text-script) > (ly:music-property (car text-script) 'text unknown) > unknown)))) > (extract-typed-music def 'note-event))) > > noteSyllable = > #(define-scheme-function > (unknown-syllable syllable-definition) > ((string? "?") ly:music?) > (let ((pitch-syllable-dictionary > (extract-syllables unknown-syllable syllable-definition))) > (pretty-print pitch-syllable-dictionary) > (lambda (pitch context) > (let* ((tonic-pitch (ly:context-property context 'tonic #{ c #})) > (tonic-syllable (ly:context-property context 'tonicSyllable > "do")) > (do-offset (inv-assoc tonic-syllable > pitch-syllable-dictionary #{ c #})) > (syllable (assoc-get (normalize-pitch (- pitch > (- tonic-pitch > do-offset))) > pitch-syllable-dictionary > unknown-syllable))) > (if (equal? syllable tonic-syllable) > (make-highlight-tonic-markup syllable) > syllable))))) > > #(set-global-staff-size 30) > > doSyllables = { > % to be entered for c major > c -do d -re e -mi f -fa g -so a -la b -ti > cis -di dis -ri fis -fi gis -si ais -li > des -ru es -mu ges -su as -lu bes -tu > } > > \layout { > ragged-right = ##t > \context { > \NoteNames > \consists Key_engraver % we need this in order to manage the 'tonic' > context property ... > \omit KeySignature % ... but we don't want to see the key signature > printed > \omit KeyCancellation > } > } > > mus = \relative c' { > c4 d e f8 fis > g4 a b c \break > > \key a \major > a,4 b cis d > e4 f8 fis g gis a4 \break > > \key d \dorian > \set tonicSyllable = re > d,4 e f g > a4 b c d \break > > \key d \minor > \set tonicSyllable = la > d,4 e f g > a4 b cis d > d c bes a > } > > << > \new Staff \mus > \new NoteNames \with { > noteNameFunction = \noteSyllable \doSyllables > } \mus > >> > > Lukas >