Impression de noms d’accords identiques à la basse différente par une oblique et nouvelle basse
Voici comment imprimer une suite d’accords nommés (objets
ChordNames) dont seule la basse diffère, indiquée par une oblique
et cette nouvelle basse, à l’aide du graveur Scheme ici défini. Son
comportement peut se gérer finement à l’aide de la propriété de contexte
chordChanges.
#(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
(chord-name:markup #f)))))
(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
>>