Hallo kil,
in Zusammenarbeit mit David sind noch eine Reihe von Änderungen und Weiterungen zu vermelden:
AllgemeingültigkeitDavid ist es gelungen die Funktion rekursiv zu definieren. Sie ist jetzt also wirklich allgemeingültig. (Du kannst jetzt auch 1024-tel benutzen, wenn Du willst.)
Eingabe "anhand der Notenhälse"Auf seine Anregung hin habe ich die Eingabe noch mal verändert. Sie orientiert sich jetzt an den Notenhälsen, wobei zu beachten ist, daß der erste Notenhals die Nummer 0 trägt. (grow-dir-var 5) setzt die Spitze jetzt also genau auf den sechsten Notenhals. (grow-dir-var 0) führt zum default-Befehl \override Beam #'grow-direction = #LEFT. Werte größer als die maximale Anzahl der Notenhälse unter dem Balken führen zu \override Beam #'grow-direction = #RIGHT. Du kannst aber auch etwas wie (grow-dir-var 3.5) eingeben, dann wird die Spitze zwischen dem vierten und fünften Notenhals zentriert. Andere Komma-Zahlen sind auch möglich.
Kneed-BeamsFür kneed-Beams gibts noch ein paar Besonderheiten.
Orientierung der SpitzeBei Buchstabe "O" konnte ich mich nicht entscheiden, ob die Spitze nach oben oder nach unten zeigen sollte. Insofern habe ich ein feature eingebaut mit dem Du die Spitze umdrehen kannst. Es funktioniert aber nur für kneed-Beams und(!) wenn der Balken horizontal ist (um sicher zu gehen, daß er horizontal ist kann man \once \override Beam #'positions = #'(0 . 0) benutzen, wobei man '(0 . 0) evtl noch anpassen muß. Natürlich müssen die beiden Zahlen gleich sein, denn sonst ist der Balken ja nicht mehr horizontal: '(0.5 . 0.5) funktioniert also, '(0 . 1) natürlich nicht).
Um die Spitze umdrehen zu können, gebe negative Zahlen ein. (Wenn es sich nicht um kneed-Beams handelt und(!) der Balken nicht horizontal ist, werden die negativen Zahlen in positive umgedeutet).
Man könnte dieses feature auch verallgemeinern. Das wäre allerdings noch sehr viel Arbeit. Da ich glaube, daß die (potenzielle) Verallgemeinerung seltenst benutzt werden wird, möchte ich mich nur dann damit beschäftigen, wenn gesteigerter Bedarf angemeldet wird.
Überstehende NotenhälseEs kann bei kneed-Beams vorkommen, daß es überstehende Notenhälse gibt (siehe Buchstabe "R").
Die äußeren, den Beam begrenzenden Notenhälse sind ein Sonderfall. Die inneren Notenhälse kannst Du im Einzelfall mit xy = \once\override Stem #'french-beaming = ##t verkürzen (siehe Code bei Buchstabe "Q"). Bei den äußeren Notenhälsen ist der erste nie ein Problem. Der letzte ist dann ein Problem, wenn er in eine andere Richtung zeigt als der erste. Um diesen Notenhals zu verkürzen hat sich David etwas einfallen lassen, was ich dann in eine Funktion verwandelt habe:
#(define ((stem-length y) grob)
(ly:grob-set-property! grob 'length y)
(ly:stem::print grob))
xyOut =
#(define-music-function (parser location y-length)(number?)
#{
\once \override Stem #'stencil = #(stem-length $y-length)
#})Anwendung z.B. bei Buchstabe "Q".
Leider gibt es zwei Einschränkungen mit dieser Funktion: Sie funktioniert nicht mit "2.14.2" sondern erst mit höheren Versionen. Ich habe es mit "2.15.13" getestet. Darüberhinaus funktioniert sie nicht in Verbindung mit \change Staff.
Vielleicht fällt uns ja noch etwas besseres ein.
\featherDurationsZusätzlich habe ich noch versucht das Ganze mit \featherDurations #(ly:make-moment 1 2) etc zu verbinden (Buchstabe "P"). Allerdings unterliegt diese Funktion so starken Beschränkungen, daß sie häufig nicht arbeitet.->
NR 1.2.4 Balken-Gespreizte Balken:
Bekannte Probleme und Warnungen
Der \featherDurations-Befehl funktioniert nur mit kurzen Notenabschnitten, und wenn die Zahlen in den Brüchen klein sind.
Aber ich denke weiter drüber nach.
Code\version "2.14.2"
\pointAndClickOff
#(set-global-staff-size 18)
\paper { tagline = ##f }
\markup \column { \bold \fill-line { "EXAMPLES" } \vspace #2 }
xy = \once\override Stem #'french-beaming = ##t
% xyOut needs "2.15.13"
#(define ((stem-length y) grob)
(ly:grob-set-property! grob 'length y)
(ly:stem::print grob))
xyOut =
#(define-music-function (parser location y-length)(number?)
#{
\once \override Stem #'stencil = #(stem-length $y-length)
#})
#(define ((grow-beam-var number) grob)
;; Thanks to David Nalesnik
(cond
((< (length (cdr (ly:grob-property (ly:grob-parent grob X) 'beaming))) 2)
(ly:beam::print grob))
((= number 0)
(begin
(ly:grob-set-property! grob 'grow-direction LEFT)
(ly:beam::print grob)))
((>= number (1- (ly:grob-array-length (ly:grob-object grob 'stems))))
(begin
(ly:grob-set-property! grob 'grow-direction RIGHT)
(ly:beam::print grob)))
((ly:stencil? (ly:beam::print grob)) ;; delete this?
(let* ((beam (ly:beam::print grob))
(dir (ly:beam::calc-direction grob))
(b-d (ly:output-def-lookup (ly:grob-layout grob) 'blot-diameter))
(beam-extent-X (ly:stencil-extent beam X))
(beam-length-x-orig (interval-length beam-extent-X))
(beam-length-x (- beam-length-x-orig b-d))
(beam-extent-Y (ly:stencil-extent beam Y))
(beam-length-y (interval-length beam-extent-Y))
(orig-beam-thickness (ly:grob-property grob 'beam-thickness))
(beam-count (length (cdr (ly:grob-property (ly:grob-parent grob X) 'beaming))))
(space-between-beams (* 0.46 (ly:grob-property grob 'gap)))
(orig-beam-length-at-stem (+ (* beam-count orig-beam-thickness)(* (- beam-count 1) space-between-beams)))
(beam-positions (ly:grob-property grob 'positions))
(beam-slant (cond ((<= (car beam-positions) (cdr beam-positions)) 1)
;;((= (car beam-positions) (cdr beam-positions)) 0)
((> (car beam-positions) (cdr beam-positions)) -1)))
(orig-slope (* beam-slant (/ (- beam-length-y orig-beam-length-at-stem) beam-length-x)))
(alpha (atan orig-slope))
(beam-thickness (* 0.8 orig-beam-thickness))
(h-max (- (/ orig-beam-length-at-stem (cos alpha)) (* 1.3 beam-thickness)))
(dir-peak (if (and (ly:grob-property grob 'knee) (< number 0) (= (car beam-positions) (cdr beam-positions)))
-1
1))
(number-a (if (integer? (abs number))
(abs number)
(inexact->exact (floor (abs number)))))
(number-b (- (abs number) (floor (abs number))))
(stems (ly:grob-object grob 'stems))
(stem-count (ly:grob-array-length stems))
(refp (ly:grob-system grob))
(first-stem (ly:grob-array-ref stems 0))
(target-stem (if (< (abs number-a) stem-count)
(ly:grob-array-ref stems number-a)
(ly:grob-array-ref stems (- stem-count 1 ))))
(next-stem (if (< (+ (abs number-a) 1) stem-count)
(ly:grob-array-ref stems (+ number-a 1))
(ly:grob-array-ref stems (- stem-count 1 ))))
(first-stem-coord (ly:grob-relative-coordinate first-stem refp X))
(target-stem-coord (ly:grob-relative-coordinate target-stem refp X))
(next-stem-coord (ly:grob-relative-coordinate next-stem refp X))
(first-stem-to-target-stem-length (interval-length (cons first-stem-coord target-stem-coord)))
(stem-to-next-stem-length (interval-length (cons target-stem-coord next-stem-coord)))
(factor (/ beam-length-x first-stem-to-target-stem-length))
;; markup-a is the longest beam
(markup-a (markup #:beam beam-length-x
(if (and (ly:grob-property grob 'knee) (< number 0)(= (car beam-positions) (cdr beam-positions)))
(* dir-peak orig-slope)
orig-slope)
beam-thickness))
;; left piece
;; y-length of left piece
(y-L
(lambda (n)
(- (/ (- beam-length-y orig-beam-length-at-stem) factor) (* dir beam-slant (* n (/ h-max (- beam-count 1)))))
))
;; x-length of left piece
(x-L (+ first-stem-to-target-stem-length (* number-b stem-to-next-stem-length)))
;; slope of left piece
(slope-part-beam-L
(lambda (n)
(cond ((or (and (> dir 0) (> beam-slant 0)) (and (< dir 0) (> beam-slant 0)))
(if (and (ly:grob-property grob 'knee) (< number 0))
(* (* 1 dir-peak) (/ (y-L n) x-L))
(* dir-peak (/ (y-L n) x-L)))
)
((or (and (> dir 0) (< beam-slant 0)) (and (< dir 0) (< beam-slant 0)))
(* -1 (/ (y-L n) x-L))))))
;; construct left piece
(part-beam-L
(lambda (n)
(markup #:beam x-L
(slope-part-beam-L n)
beam-thickness)))
;; markup of left piece
(markup-L (lambda (n) (markup (part-beam-L n))))
;; stencil of left piece
(beam-part-L (lambda (n) (grob-interpret-markup grob (markup-L n))))
;; y-extent of left piece
(beam-part-L-ext-y (lambda (n) (ly:stencil-extent (beam-part-L n) Y)))
;; length of left piece
(length-beam-part-L-y (lambda (n) (interval-length (beam-part-L-ext-y n))))
;; right piece 0.86
(y-R (lambda (n) (- (- beam-length-y orig-beam-length-at-stem) (y-L n))))
(x-R (- beam-length-x x-L))
(slope-part-beam-R
(lambda (n)
(cond
((or (and (> dir 0) (> beam-slant 0)) (and (< dir 0) (> beam-slant 0)))
(if (and (ly:grob-property grob 'knee) (< number 0))
(* (* 1 dir-peak) (/ (y-R n) x-R))
(/ (y-R n) x-R))
)
((or (and (> dir 0) (< beam-slant 0)) (and (< dir 0) (< beam-slant 0)))
(* -1 (/ (y-R n) x-R))))))
(part-beam-R
(lambda (n)
(markup #:beam (- beam-length-x x-L)
(slope-part-beam-R n)
beam-thickness)))
(markup-R (lambda (n) (markup (part-beam-R n))))
;; parts of feathered beams
(beam-pieces
(map
(lambda (n)
(ly:stencil-combine-at-edge
(ly:stencil-translate-axis
(grob-interpret-markup grob (markup-L n))
-0.025 X)
X RIGHT
(ly:stencil-translate-axis
(grob-interpret-markup grob (markup-R n))
(cond ((and (> dir 0)(> beam-slant 0))
(if (and (>= (slope-part-beam-L n) 0)(>= (slope-part-beam-R n) 0))
(- (length-beam-part-L-y n) beam-thickness)
(* -1 (- (length-beam-part-L-y n) beam-thickness))))
((and (> dir 0)(< beam-slant 0))
(* -1 (- (length-beam-part-L-y n) beam-thickness)))
((and (< dir 0)(> beam-slant 0))
(* dir-peak (- (length-beam-part-L-y n) beam-thickness)))
((and (< dir 0)(< beam-slant 0))
(if (and (<= (slope-part-beam-L n) 0)(<= (slope-part-beam-R n) 0))
(* -1 (- (length-beam-part-L-y n) beam-thickness))
(- (length-beam-part-L-y n) beam-thickness)))
)
Y)
0))
(cdr (iota beam-count))))
) ;; end of defs in let*
(define (helper beam-pieces)
(ly:stencil-add
(car beam-pieces)
(if (null? (cdr beam-pieces))
(car beam-pieces)
(helper (cdr beam-pieces)))))
(ly:stencil-translate-axis
(ly:stencil-add
;; first (long beam)
(ly:stencil-translate-axis
(grob-interpret-markup grob markup-a)
-0.025 X)
;; other beams
(helper beam-pieces))
(car beam-positions)
Y)
) ;; end of let*
)
)
)
%--------------------- Test ----------------------------------------------------
\relative c' {
\mark\markup { \with-color #red "A" }
\once \override Beam #'stencil = #(grow-beam-var 0)
c512[ d e f g a b c] s128
\mark\markup { \with-color #red "B" }
\once \override Beam #'stencil = #(grow-beam-var 5)
c,32[ d e f g a b c]
\mark\markup { \with-color #red "C" }
\once \override Beam #'stencil = #(grow-beam-var 3.5)
a64[ g f e d c b a]
\mark\markup { \with-color #red "D" }
\once\override Beam #'stencil = #(grow-beam-var 5)
c,32 [c c c c c c c c c c c c c c c
]
\bar "" \break
\mark\markup { \with-color #red "E" }
\once \override Beam #'stencil = #(grow-beam-var 5)
c''32 [d' e, f g a b, c d'' e f g, a b c d
]
\mark\markup { \with-color #red "F" }
\once \override Beam #'stencil = #(grow-beam-var 5)
c,,32 [d e f g a b c d e f g a b c d
]
\bar ""\break
\mark\markup { \with-color #red "G" }
\once \override Beam #'stencil = #(grow-beam-var 5)
c32 [b a g f e d c b a g f e d c b
]
\mark\markup { \with-color #red "H" }
\once\override Beam #'stencil = #(grow-beam-var 5)
c,32 [c' c' c,, c d e f g c e b' c'
]
\bar ""\break
\mark\markup { \with-color #red "J" }
\once \override Beam #'stencil = #(grow-beam-var 5)
c,,,32[ e g b d f a c]
\mark\markup { \with-color #red "K" }
\once\override Beam #'stencil = #(grow-beam-var 4)
c,,256[c' c' c' c']
\bar "" \break
\mark\markup { \with-color #red "L" }
\once \override Beam #'positions = #'(0 . 0)
\once \override Beam #'stencil = #(grow-beam-var -5)
f,,,,,32 [ \xy f''' f,,, \xy f''' f,,, %{ \xy %} f''' f,,, \xy f''' f,,, \xyOut #11 f''']
\override Beam #'auto-knee-gap = #6
\once \override Beam #'stencil = #(grow-beam-var 5)
f,, [f'' f,, f'' f,, f'' f,, f'']
}
% --> http://lsr.dsi.unimi.it/LSR/Item?id=508
\new PianoStaff <<
\new Staff = "RH" { \clef treble \time 3/4 s2 }
\new Staff = "LH" { \clef bass \time 3/4 s2 }
\context Staff = LH
\relative {
\mark\markup { \column { \vspace #3 \with-color #red "M" } }
\stemDown
\once\override Beam #'stencil = #(grow-beam-var 5)
\override Beam #'concaveness = #0
c,,32 [ g'
\change Staff = RH
d' a' e' b' fis' cis']
\once\override Beam #'stencil = #(grow-beam-var 5)
cis32 [fis, b, e, a, d,
\change Staff = LH
g, c, ]
}
>>
one =
\relative c' {
\once\override Beam #'stencil = #(grow-beam-var 5)
c'32 [c c c c c c c c c c c c c c c] c2
}
two =
\relative c' {
\once\override Beam #'stencil = #(grow-beam-var 5)
c,16 [c c c c c c c c c c c c c c c]
}
<<{ \one } \\ {\two }>>
expr = { a1*1/8\< s4.\! s8\> s s s8\! }
\relative c'' {
\mark\markup { \column { \vspace #3 \with-color #red "N" } }
\override Hairpin #'minimum-length = #5
\override Beam #'stencil = #(grow-beam-var 5)
a1*1/8\< s4.\! s8\> s s s8\!
a16 [a a a a a a a a a a a a a a a]
a32 [a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a]
a64 [a a a
a a a a
a a a a
a a a a
a a a a
a a a a
a a a a
a a a a]
a2
}
\pageBreak
\relative c' {
\mark\markup { \with-color #red "O" }
\once \override Beam #'positions = #'(0.2 . 0.2)
\override Beam #'auto-knee-gap = #4
\override Beam #'stencil = #(grow-beam-var -16)
c''32 [b a g
f g a b
c b a g
f g a b
\xy e,,, c''' b a
g a b c
d c b a
g a b c]
\bar "" \break
\override Beam #'auto-knee-gap = #4
\override Beam #'stencil = #(grow-beam-var 16)
c32 [b a g
f g a b
c b a g
f g a b
e,,, c''' b a
g a b c
d c b a
g a b c]
}
\relative c'' {
\mark\markup { \with-color #red "P" }
\override Beam #'stencil = #(grow-beam-var 4)
\featherDurations #(ly:make-moment 1 2)
{c32[ c c c} \featherDurations #(ly:make-moment 2 1) {c c c c]} c2.
}
\relative c'' {
\override Beam #'stencil = #(grow-beam-var 8)
\featherDurations #(ly:make-moment 1 2)
{a64 [a a a
a a a a}
\featherDurations #(ly:make-moment 2 1)
{
a a a a
a a a a
a a a a
a a a a
a a a a
a a a a]}
a2|
}
\relative c {
\mark\markup { \with-color #red "Q" }
\once \override Beam #'positions = #'(0 . 0)
\once \override Beam #'stencil = #(grow-beam-var -5)
f32 [ \xy f''' f,,, \xy f''' f,,, %{ \xy %} f''' f,,, \xy f''' f,,, %\xy
\xyOut #11
f''']
}
top = \change Staff = "1"
bottom = \change Staff = "2"
music = \relative c {
\mark\markup { \with-color #red "R" }
\override Beam #'auto-knee-gap = #0
\set tupletSpannerDuration = #(ly:make-moment 1 16)
\override TupletNumber #'transparent = ##t
\override Beam #'stencil = #(grow-beam-var -1)
\once \override Beam #'positions = #'(4.5 . 5)
\times 2/3 {
\bottom c32[ g' \top eis']
\once \override Beam #'positions = #'(-4.5 . -6)
c'[ e, \bottom g,]
\top e''[ \bottom c,, \top g'']
}
\override Beam #'stencil = #(grow-beam-var 2)
%\once \override Beam #'positions = #'(3.5 . 5)
\once \override Beam #'positions = #'(4 . 4)
\times 4/5 {
\bottom c,,64[ \top \xy g'' \xy e' \bottom c,, \top c'']
}
}
\score {
\new PianoStaff <<
\new Staff = "1" {
s4
}
\new Staff = "2" {
\clef bass
\music
}
>>
}Dann weiter viel Spaß mit den Beams.
Harm
P.S.
Wenn du mal in Berlin bist lade ich dich auf ein Kaffee ein 
Gibt's auch Kuchen dazu?
