Hallo Leonach,
ich hab' mal zwei Funktionen dazu entwickelt:
\version "2.14.2"
#(define (list->iv l1 l2 number)
"list->iv converts a list (l1) into a list of pairs (l2).
The elements of l1 will be modified by number.
e.g (list->iv '(1 2 3 4) '() 0.1)
((1.1 . 1.9) (2.1 . 2.9) (3.1 . 3.9))
"
(set! l2 (cons (cons (+ (car l1) number) (- (cadr l1) number)) l2))
(if (= (length (cdr l1)) 1)
(reverse l2)
(list->iv (cdr l1) l2 number)))
#(define (list->iv-2 init l1 l2 number)
"
init is supposed to be (car l1).
list->iv-2 converts a list (l1) into a list of pairs (l2).
The elements of l1 will be modified by number.
e.g (list->iv-2 1 '(1 2 3 4) '() 0.1)
-> ((0.9 . 2.1) (0.9 . 3.1) (0.9 . 4.1))
"
(set! l2 (cons (interval-widen (cons init (cadr l1)) number) l2))
(if (= (length (cdr l1)) 1)
(reverse l2)
(list->iv-2 init (cdr l1) l2 number)))
#(define (stack-stencils stencil stils)
"
stils is supposed to be a list of stencils.
stack-stencil will add all elements of stils
to the initial stencil.
"
(set! stencil (ly:stencil-add stencil (car stils)))
(if (null? (cdr stils))
stencil
(stack-stencils stencil (cdr stils))))
#(define (combine-stencils l1 l2 l3 l4 padding)
"
l1 and l2 are supposed to be lists of stencils.
l4 is supposed to be a list of pairs.
combine-stencils will return a new list of stencils (l3)
built from the elements of l1 and l2.
"
(set! l3 (cons (ly:stencil-combine-at-edge
(car l1)
X RIGHT
(ly:stencil-translate-axis
(if (null? l2) point-stencil (car l2))
(interval-center (car l4)) Y)
padding) l3))
(if (null? (cdr l1))
l3
(combine-stencils (cdr l1) (if (null? l2) '() (cdr l2)) l3 (cdr l4) padding)))
#(define (combine-stencils-2 stencil l1 padding)
"
l1 is supposed to be a list of stencils.
stencil is supposed to be (car l1).
combine-stencils-2 will return a new stencil built
of all elements of l1.
"
(set! stencil (ly:stencil-combine-at-edge stencil X RIGHT (car l1) padding))
(if (null? (cdr l1))
stencil
(combine-stencils-2 stencil (cdr l1) padding)))
chordAnalysis =
#(define-music-function (parser location text-list)(list?)
"
chordAnalysis overrides Arpeggio-stencil, returning a new stencil
with brackets between the note-heads of a chord.
The elements of the text-list-argument will add a text to the brackets
"
#{
\once \override Arpeggio #'stencil =
#(lambda (grob)
(let* ((par (ly:grob-parent (ly:grob-parent grob Y) Y))
(staff-line-thickness (ly:staff-symbol-line-thickness grob))
(note-heads (ly:grob-object par 'note-heads))
(note-heads-grobs (if (not (null? note-heads))
(ly:grob-array->list note-heads)
'()))
(staff-pos (map (lambda (x) (/ (ly:grob-property x 'staff-position) 2)) note-heads-grobs))
(iv-list (list->iv staff-pos '() (/ staff-line-thickness 1)))
(stils (map (lambda (x) (ly:bracket Y x staff-line-thickness (* -3 staff-line-thickness))) iv-list))
(texts (map (lambda (x) (grob-interpret-markup grob (markup #:vcenter #:fontsize -7 x))) $text-list))
(lst (combine-stencils stils texts '() iv-list 1))
(new-stencil (stack-stencils (car lst) (cdr lst))))
new-stencil))
\once \override Arpeggio #'color = #red
\once \override Arpeggio #'direction = #RIGHT
\once \override Arpeggio #'before-line-breaking =
#(lambda (grob)
(let* ((stil (ly:grob-property grob 'stencil))
(stil-ext (ly:stencil-extent stil X)))
(ly:grob-set-property! grob 'X-extent (interval-widen stil-ext 0.5))))
$(make-music 'EventChord 'elements (list (make-music 'ArpeggioEvent)))
#})
chordAnalysisII =
#(define-music-function (parser location text-list)(list?)
"
chordAnalysis overrides Arpeggio-stencil, returning a new stencil
with brackets between the note-heads of a chord.
Each bracket will start at the bass-note.
The elements of the text-list-argument will add a text to the brackets
"
#{
\once \override Arpeggio #'stencil =
#(lambda (grob)
(let* ((par (ly:grob-parent (ly:grob-parent grob Y) Y))
(staff-line-thickness (ly:staff-symbol-line-thickness grob))
(note-heads (ly:grob-object par 'note-heads))
(note-heads-grobs (if (not (null? note-heads))
(ly:grob-array->list note-heads)
'()))
(staff-pos (map (lambda (x) (/ (ly:grob-property x 'staff-position) 2)) note-heads-grobs))
(iv-list (list->iv-2 (car staff-pos) staff-pos '() (* 2 staff-line-thickness)))
(stils (map (lambda (x) (ly:bracket Y x staff-line-thickness (* -3 staff-line-thickness))) iv-list))
(texts (map (lambda (x) (grob-interpret-markup grob (markup #:vcenter #:fontsize -3 x))) $text-list))
(lst (reverse (combine-stencils stils texts '() iv-list 1)))
(new-stencil (combine-stencils-2 (car lst) (cdr lst) 1)))
new-stencil))
\once \override Arpeggio #'color = #red
\once \override Arpeggio #'direction = #RIGHT
\once \override Arpeggio #'before-line-breaking =
#(lambda (grob)
(let* ((stil (ly:grob-property grob 'stencil))
(stil-ext (ly:stencil-extent stil X)))
(ly:grob-set-property! grob 'X-extent (interval-widen stil-ext 0.5))))
$(make-music 'EventChord 'elements (list (make-music 'ArpeggioEvent)))
#})
%------------- test
\paper {
indent = 0
ragged-right = ##f
}
\layout {
\context {
\Score
\override BarNumber #'stencil = #point-stencil
}
}
txt = {
\textLengthOn
\override Score.TextScript #'padding = #3
s1^"Dur-Akkord"
s1^"moll-Akkord"
s1^"Sext-Akkord"
s1^"Quart-Sext-Akkord"
s1^"Dominant-Sekund-Akkord"
s1^"Aufgabe: Bestimme die Intervalle!"
}
chrds = \relative c' {
\chordAnalysis #'("große Terz" "kleine Terz")
<c e g>1
\chordAnalysis #'("kleine Terz" "große Terz")
<d f a>
\chordAnalysis #'("kleine Terz" "Quarte")
<e g c>
\chordAnalysis #'("Quarte" "große Terz")
<f bes d>
\chordAnalysis #'("große Sekunde" "große Terz" "kleine Terz")
<f g b d>
\chordAnalysis #'("......""......""......""......""......""......")
<c e g bes d fis a>
}
\markup \fill-line { \center-column { \bold "Version I" "Intervalbestimmung von Ton zu Ton" \vspace #2 } }
\new Staff <<
\new Voice \txt
\new Voice \chrds
>>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
txtII = {
\textLengthOn
\override Score.TextScript #'padding = #3
s1^"Dur-Akkord"
s1^"moll-Akkord"
s1^"Sext-Akkord"
s1^"Quart-Sext-Akkord"
s1^"Dominant-Sekund-Akkord"
s1^"Aufgabe: Bestimme die Intervalle!"
}
chrdsII = \relative c' {
\chordAnalysisII #'("große Terz" "Quinte")
<c e g>1
\chordAnalysisII #'("kleine Terz" "große Quinte")
<d f a>
\chordAnalysisII #'("kleine Terz" "kleine Sexte")
<e g c>
\chordAnalysisII #'("Quarte" "große Sexte")
<f bes d>
\chordAnalysisII #'("große Sekunde" "überm. Quarte" "große Sexte")
<f g b d>
\chordAnalysisII #'("......""......""......""......""......""......")
<c e g bes d fis a>
}
\markup \fill-line { \center-column { \bold "Version II" "Intervalbestimmung vom Baß aus zu jedem Ton" \vspace #2 } }
\new Staff <<
\new Voice \txtII
\new Voice \chrdsII
>>
HTH,
Harm