Print chord names with same root and different bass as slash and bass note
Appearance
(Redirected from LSR 1137)
To print subsequent chord names only differing in their bass note as slash and bass note without a root symbol, use the Scheme engraver defined in this snippet. The behaviour is controlled by the chordChanges context property.
\version "2.24"
#(define Bass_changes_equal_root_engraver
(lambda (ctx)
"Drop root for follow-up chord names that differ only in bass.
In other words, the chord name sequence 'D D/C D/B' gets actually
printed as 'D /C /B'.
Set the `chordChanges` context property to `#t` to activate this
feature."
(let ((chord-pitches '())
(last-chord-pitches '())
(bass-pitch #f))
(make-engraver
((initialize this-engraver)
(let ((chord-note-namer (ly:context-property ctx
'chordNoteNamer)))
;; Set `chordNoteNamer`, respecting user setting if already
;; done.
(ly:context-set-property! ctx 'chordNoteNamer
(if (procedure? chord-note-namer)
chord-note-namer
note-name->markup))))
(listeners
((note-event this-engraver event)
(let* ((pitch (ly:event-property event 'pitch))
(pitch-name (ly:pitch-notename pitch))
(pitch-alt (ly:pitch-alteration pitch))
(bass (ly:event-property event 'bass #f))
(inversion (ly:event-property event 'inversion #f)))
;; We look at the `bass` and `inversion` event properties
;; to decide how to handle the current note event. If
;; `inversion` is set we add the bass note to the chord as
;; an ordinary member so that we can compare inversed
;; chords; if `bass` is set the bass note is not added to
;; the chord.
;;
;; In the `chord-pitches` list we actually collect only
;; the notes' pitch names (which are integers) and pitch
;; alterations as pairs, ignoring the octave.
(cond (bass (set! bass-pitch pitch))
(inversion
(set! bass-pitch pitch)
(set! chord-pitches
(cons (cons pitch-name pitch-alt)
chord-pitches)))
(else
(set! chord-pitches
(cons (cons pitch-name pitch-alt)
chord-pitches)))))))
(acknowledgers
((chord-name-interface this-engraver grob source-engraver)
(let ((chord-changes (ly:context-property ctx
'chordChanges #f)))
;; If subsequent chords are equal apart from their bass,
;; we change the `text` property to print only the slash
;; and the bass note (via the formatter stored in the
;; `chordNoteNamer` context property).
;;
;; Equality is tested by comparing the sorted lists of
;; this chord's elements and the previous chord. Sorting
;; is needed because inverted chords may have a different
;; order of pitches. Note that we only do a simplified
;; sorting using the pitch name, ignoring the alteration.
(if (and bass-pitch
chord-changes
(equal? (sort chord-pitches car<)
(sort last-chord-pitches car<)))
(ly:grob-set-property!
grob 'text
(make-line-markup
(list
(ly:context-property ctx 'slashChordSeparator)
((ly:context-property ctx 'chordNoteNamer)
bass-pitch
(ly:context-property ctx
'chordNameLowercaseMinor))))))
(set! last-chord-pitches chord-pitches)
(set! chord-pitches '())
(set! bass-pitch #f))))
((finalize this-engraver)
(set! last-chord-pitches '()))))))
myChords = \chordmode {
% \germanChords
\set chordChanges = ##t
d2:m d:m/cis
d:m/c
\set chordChanges = ##f
d:m/b
e1:7
\set chordChanges = ##t
e
\break
\once \set chordChanges = ##f
e1/f
e2/gis e/+gis e e:m/f d:m d:m/cis d:m/c
\set chordChanges = ##f
d:m/b
}
<<
\new ChordNames
\with { \consists #Bass_changes_equal_root_engraver }
\myChords
\new Staff \myChords
>>