Jump to content

Function to create WYGIWYM-Chord Names

From LilyPond wiki

This function is an update to an earlier version which can be found here: http://lists.gnu.org/archive/html/lilypond-user/2009-02/msg00293.html

The function is customised to work with a special font which can also be found in the above link. It shouldn't be too difficult to get the function to work with other fonts.

I created this function because the internal ChordNames context generates chord symbols only by chord entry ( <c e g> ) which often leads to misinterpretation and strange chord symbols are the result.

What this function basically does is taking note-input and converting it to a lyric-context. For example c-"7" will print C7 chord symbol.

The advantage of this function is that the input can still be transposed before it gets converted, i.e. \transpose c d c-"7" will print D7 chord symbol.

The following entries are possible:

c

→ C

c-"7"

→ C7

<c e>

→ C/E

<c e>-"7"

→ C7/E

r

→ N.C.

s

s-"text"

→ text [not affected by transposition]

and these three additional functions work with any of the above (except for skip)

\parenLeft c

→ (C

\parenRight c

→ C)

\parenBoth c

→ (C)

\version "2.24.0"

%% http://lsr.di.unimi.it/LSR/Item?id=608
%% see also http://lilypond.1069038.n5.nabble.com/LSR-v-2-18-quot-Function-to-create-WYGIWYM-Chord-Names-quot-does-not-compile-tc159364.html

%LSR created by TaoCG

#(define (music-elts x)
   (ly:music-property x 'elements))

#(define (EventChord? x)
   (eq? (ly:music-property x 'name) 'EventChord))

#(define (NoteEvent? x)
   (eq? (ly:music-property x 'name) 'NoteEvent))

#(define (RestEvent? x)
   (eq? (ly:music-property x 'name) 'RestEvent))

#(define (SkipEvent? x)
   (eq? (ly:music-property x 'name) 'SkipEvent))

#(define (root-name x)
   (let ((n (ly:pitch-notename (ly:music-property x 'pitch))))
     (case n
       ((0) "C")
       ((1) "D")
       ((2) "E")
       ((3) "F")
       ((4) "G")
       ((5) "A")
       ((6) "B"))))

#(define (root-alter x)
   (let ((a (ly:pitch-alteration (ly:music-property x 'pitch))))
     (case a
       ((-1) "<")
       ((-1/2) "b")
       ((0) "")
       ((1/2) "#")
       ((1) ">"))))

#(define (bass-name x)
   (let ((n (ly:pitch-notename (ly:music-property x 'pitch))))
     (case n
       ((0) "e")
       ((1) "r")
       ((2) "t")
       ((3) "z")
       ((4) "u")
       ((5) "q")
       ((6) "w"))))

#(define (bass-alter x)
   (let ((a (ly:pitch-alteration (ly:music-property x 'pitch))))
     (case a
       ((-1) ";")
       ((-1/2) ",")
       ((0) "")
       ((1/2) "'")
       ((1) "\""))))

#(define (symbolize-chord music)
   (if (EventChord? music)
     (let* ((i (length (music-elts music)))
                (event (car (music-elts music)))
                (dur (ly:music-property event 'duration))
                (root "")
                (bass "")
                (r-alt "")
                (b-alt "")
                (suffix "")
                (paren-left "")
                (paren-right ""))
           (when (NoteEvent? event)
             (set! root (root-name event))
       (set! r-alt (root-alter event))
       (if (eq? (ly:music-property event 'parenleft) #t)
           (set! paren-left "["))
       (if (eq? (ly:music-property event 'parenright) #t)
           (set! paren-right "]"))
       (if (= i 2)
           (let ((event-two (cadr (music-elts music))))
             (if (NoteEvent? event-two)
               (when (NoteEvent? event-two)
                 (set! bass (string-append "_" (bass-name event-two)))
                 (set! b-alt (bass-alter event-two)))
               (set! suffix (ly:music-property event-two 'text)))))
       (if (= i 3)
           (let ((event-two (cadr (music-elts music)))
                 (event-three (car (cddr (music-elts music)))))
             (set! bass (string-append "_" (bass-name event-two)))
             (set! b-alt (bass-alter event-two))
             (set! suffix (ly:music-property event-three 'text)))))
           (when (RestEvent? event)
             (set! root "N.C.")
       (if (eq? (ly:music-property event 'parenleft) #t)
           (set! paren-left "["))
       (if (eq? (ly:music-property event 'parenright) #t)
           (set! paren-right "]")))
           (if (and (SkipEvent? event) (> i 1))
       (set! suffix (ly:music-property (cadr (music-elts music)) 'text)))
             (set! music (make-music
                           'LyricEvent
                   'duration dur
                   'text
                   (string-append
                     paren-left root r-alt suffix bass b-alt paren-right)))))
   music)

%% Updaters Remark:
%% Simply using `event-chord-wrap!' to get old behaviour back is pretty lazy.
%% Alas, do we need this snippet anymore at all? --Harm
chordSymbols =
#(define-music-function (music) (ly:music?)
   (music-map
     (lambda (x) (symbolize-chord x))
     (event-chord-wrap! music)))

parenLeft =
#(define-music-function (music) (ly:music?)
   (ly:music-set-property!
    (if (EventChord? music)
        (car (ly:music-property music 'elements))
        music)
    'parenleft #t)
     music)

parenRight =
#(define-music-function (music) (ly:music?)
   (ly:music-set-property!
    (if (EventChord? music)
        (car (ly:music-property music 'elements))
        music)
    'parenright #t)
     music)

parenBoth =
#(define-music-function (music) (ly:music?)
  (parenLeft (parenRight music)))


<<
  \new Staff = "s" \new Voice = "v" { g'2 c' f'1 bes'2 es' a' d' }
  \new Lyrics \with { alignAboveContext = "s" } {
    %\override LyricText.font-name = "JazzChords"
    \set associatedVoice = "v"
    \chordSymbols {
      \transpose c f {
        \parenLeft
        d2-"m7"
        <g b>-"13"
        c1-"M"

        s2
        s-"|: A7 :|"
        \parenRight
        r
      }
    }
  }
>>