Autor Thema: komplexe Akkord - bessere Lösung?  (Gelesen 7496 mal)

kilgore

  • Member
komplexe Akkord - bessere Lösung?
« am: Mittwoch, 25. Juli 2012, 18:03 »
Liebe Lilys!

Ich habe eine "komplexe" Akkord zu setzen und bin mit den Resultaten nicht so ganz zufrieden:

\version "2.14.2"

\relative c, {
  \clef bass
  <c! cis d es g>
}

Es geht um C und Cis, und das nah liegende D. Irgendwie finde ich das einfach unschön. Die gewöhnlich Lösung in den Snippets
http://lsr.dsi.unimi.it/LSR/Item?id=505
ist für die Stelle auch ungünstig weil das Akkord ziemlich oft kommt und das auch in komplexe Situationen wo die einbau von noch einer zusätzliche Stimme sehr mühsam wäre.

Also frage ich euch: wer hat schon ein bessere Lösung für solche Situationen gefunden?

Danke!!

Gruß
kil


trulli

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #1 am: Mittwoch, 25. Juli 2012, 21:56 »
Hi Kil,

ich würde aus dem c einfach ein his (bzw bis) machen, dann kann man die Struktur erkennen. Ein andere Möglichkeit wäre es (wie bei Penderecki) ein Cluster zu notieren, vor dem in kleinen Noten die einzelnen Töne stehen. Das wäre natürlich mehr Aufwand.

\version "2.14.2"

\relative c, {
  \clef bass
  <bis cis d es g>
}

Gruß von Trulli

kilgore

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #2 am: Mittwoch, 25. Juli 2012, 23:56 »
hi trulli!

Ja das His ist zur Zeit die "Notlösung". Das Resultat ist natürlich viel schöner, aber irgendwie doch "was anderes". Vielleicht ist aber eine alternative Kluster-Notation wie bei Penderecki ein Überlegung Wert....

Gruß
kil

harm6

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #3 am: Samstag, 28. Juli 2012, 23:38 »
Hallo kilgore,

nach einer Idee von Mike Solomon habe ich mal etwas entworfen:

\splayedStemChord
  #'(0 -4.2 1.5 0 0)
  #'(0 0 0 0 0)
<c! cis d es g>

Die Funktion hat zwei Listen als Argumente. Beide sollten so viele Elemente beinhalten wie der Akkord Töne hat.
Die erste Liste verschiebt Notenköpfe. Die Werte sind Multiplikatoren. Bei einem Wert von 0 passiert also gar nichts.
Die zweite Liste besteht aus Summanden, die als Korrektiv für die Verschiebung der Vorzeichen dienen können. Sehr häufig reicht die 0 schon aus, aber ganz auf diese Liste zu verzichten geht leider nicht, sonst kann man mache Kollision nicht bereinigen.
Allerdngs benötigt diese Funktion eine der neueren devel-Versionen.

\version "2.15.39"

\paper {
        indent = 25
        print-all-headers = ##t
}

#(define ((positioning-done l1 l2) grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (default-nh-x-width (interval-length (ly:stencil-extent (ly:note-head::print grob) X)))
           (accidental-grobs (map (lambda (x) (ly:grob-object x 'accidental-grob)) nh))
           (sys (ly:grob-parent (ly:grob-parent (ly:grob-parent grob X) X) X))
           (nh-ref-pts (map (lambda (x) (ly:grob-relative-coordinate x sys X)) nh))
           (acc-ref-pts
             (map
               (lambda (x) (if (ly:grob? x) (ly:grob-relative-coordinate x sys X) #f))
                 accidental-grobs)))

  ;; note-heads
      (for-each
        (lambda (x y z)
          (ly:grob-translate-axis! x (* y z) X))
            nh (iota (length nh)) l1)
       
  ;; accidentals
      (for-each
        (lambda (a b c d add)
    (if (null? a)
      #f
                  (ly:grob-translate-axis! a (- (* b c) d default-nh-x-width add) X)))
          accidental-grobs (iota (length nh)) l1 acc-ref-pts l2)))
    0.0)

#(define (splayed-stem-stencil grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((pc (ly:grob-parent (ly:grob-parent grob X) X))
           (nc (ly:grob-parent grob Y))
           (dir (ly:grob-property grob 'direction))
           (half-space (* 0.5 (ly:staff-symbol-staff-space grob)))
           (thick (* (ly:grob-property grob 'thickness)
                     (ly:staff-symbol-line-thickness grob)))
           (y1 (* half-space (ly:stem::calc-stem-begin-position grob)))
           (y2 (- (* half-space (ly:stem::calc-stem-end-position grob)) (* 2 thick)))
           (nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (x (ly:grob-relative-coordinate (car nh) pc X))
           (first-nh-staff-pos (ly:grob-property (car nh) 'staff-position))
           (targets-staff-pos (map (lambda (x) (ly:grob-property x 'staff-position)) nh))
           (sorted-targets-staff-pos (sort targets-staff-pos <))
           (beam (ly:grob-object grob 'beam))
           (beam-corr (if (and (= dir -1) (ly:grob? beam)) -1 1))
           (corr-add (if (and (>= first-nh-staff-pos (car sorted-targets-staff-pos)) (= dir 1))
                       (/ (- first-nh-staff-pos (car sorted-targets-staff-pos)) 2)
                       (/ (- first-nh-staff-pos (car (reverse sorted-targets-staff-pos))) 2)))
           (stem-y-corr (map (lambda (x)  (+  (/ (- x first-nh-staff-pos) 2) corr-add)) targets-staff-pos))
           (stencil (apply
                      ly:stencil-add
                      (map (lambda (nh y)
                             (let ((my-x (car (ly:grob-extent nh pc X))))
                               (make-line-stencil thick x (* beam-corr y2) my-x (+  y y1))))
                           nh stem-y-corr))))
    stencil)))

#(define (new-flag-stencil grob)
    (let* ((stil (ly:flag::print grob))
           (stem (ly:grob-parent grob X))
           (dir (ly:grob-property stem 'direction))
           (thick (* (ly:grob-property stem 'thickness)
             (ly:staff-symbol-line-thickness grob)))
           (x-ext (ly:stencil-extent stil X))
           (y-ext (ly:stencil-extent stil Y))
           (line-stil (make-line-stencil thick (car x-ext) (car y-ext) (car x-ext) (cdr y-ext)))
           (new-stil (ly:stencil-translate-axis
                         (ly:stencil-combine-at-edge
                           stil
                           X LEFT
                           line-stil 0)
                             (* dir (- (interval-length y-ext) (* 3 thick))) Y)))
    new-stil))
   
#(define (new-X-extent grob)
;; TODO Better spacing
  (let* ((x-ext (ly:grob-property grob 'X-extent)))
  (ly:grob-set-property! grob 'X-extent (cons (* 2 (car x-ext)) (* 2 (cdr x-ext))))))
   
splayedStemChord =
#(define-music-function (parser location l1 l2 mus)
   (list? list? ly:music?)
#{
        \once \override Flag #'stencil = #new-flag-stencil
        \once \override Score.NoteColumn #'before-line-breaking = #new-X-extent
        \once \override Stem #'positioning-done = #(positioning-done l1 l2)
        \once \override Stem #'stencil = #splayed-stem-stencil
                 
         $mus

#})
 
%%%%%%%%%%% test %%%%%%%%%%%%%%%%%%%%%%%%%%%

m¹ = \relative c {
         \clef bass
         \voiceOne
         c4
         \splayedStemChord
         % Note-head-offsets. Note: elements are multipliers.
           #'(0 -4 3.5 -2.5 0.9 0 1.6)
         % Accidental-offsets, elements are added to the calculated values.
           #'(0 0 0 0 0 1 0)
         <b,! dis bes f'! d! d! gis>8
         
         d'8 e f! g a
}

m² = \relative c {
         \clef bass
         \voiceTwo
         c4
         \once \override Beam #'positions = #'(-9 . -3.5)
         \splayedStemChord
           #'(0 -4 3.5 -2.5 0.9 0 1.6)
           #'(0  0 0    0   0   1 0)
         <b,! dis bes f'! d! d! gis>8
         
         d'8 e f! g a
}

m³ = \relative c, {
  \clef bass
  \accidentalStyle "forget"
 
  <c! cis d es g>
  \repeat unfold 3 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>
          \noBeam
  }
  \voiceTwo
  \repeat unfold 4 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>
          \noBeam
  }
  \oneVoice
  \repeat unfold 8 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(0 0 0 0 0)
          <c! cis d es g>
  }
}

\score {
        \new StaffGroup <<
          \new Staff \with { instrumentName = "One Voice" }
            { \m¹ \m² }
         
          \new Staff \with { instrumentName = "Two Voices" }
            \repeat unfold 2 {
            <<
            \new Voice \transpose c c'\m¹
            \new Voice \m²
            >>
            }
           
          \new Staff \with { instrumentName = "kilgore's chord " }
            \m³
         
          \new Staff \with { instrumentName = "control" }
            \relative c' { \clef bass  \repeat unfold 8 { r4 } }
        >>
        \header {
        dedication = \markup {
                \center-column {
                "Thanks to Mike Solomon"
                \line { see \with-url #"http://lists.gnu.org/archive/html/lilypond-user/2011-12/msg00421.html" \italic "this thread" }
                \vspace #1
                }
        }
        title = \markup {
                \center-column {
                "Complex chords"
                "with"
                "splayed stems"
                \vspace #2
                }
        }
        }
}

harm6

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #4 am: Montag, 30. Juli 2012, 00:18 »
Hier noch eine "2.14.2"-Variante:

\version "2.14.2"

\paper {
        indent = 25
        print-all-headers = ##t
}

#(define ((positioning-done l1 l2) grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (default-nh-x-width (interval-length (ly:stencil-extent (ly:note-head::print grob) X)))
           (accidental-grobs (map (lambda (x) (ly:grob-object x 'accidental-grob)) nh))
           (sys (ly:grob-parent (ly:grob-parent (ly:grob-parent grob X) X) X))
           (nh-ref-pts (map (lambda (x) (ly:grob-relative-coordinate x sys X)) nh))
           (acc-ref-pts
             (map
               (lambda (x) (if (ly:grob? x) (ly:grob-relative-coordinate x sys X) #f))
                 accidental-grobs)))

  ;; note-heads
      (for-each
        (lambda (x y z)
          (ly:grob-translate-axis! x (* y z) X))
            nh (iota (length nh)) l1)
       
  ;; accidentals
      (for-each
        (lambda (a b c d add)
    (if (null? a)
      #f
                  (ly:grob-translate-axis! a (- (* b c) d default-nh-x-width add) X)))
          accidental-grobs (iota (length nh)) l1 acc-ref-pts l2)))
    0.0)
   
#(define (new-flag-stencil grob)
    (let* ((stil (ly:stem::calc-flag grob))
           (nc (ly:grob-parent grob X))
           (dir (ly:grob-property grob 'direction))
           (thick (* (ly:grob-property grob 'thickness)
             (ly:staff-symbol-line-thickness grob)))
           (x-ext (ly:stencil-extent stil X))
           (y-ext (ly:stencil-extent stil Y))
           (line-stil (make-line-stencil thick (car x-ext) (car y-ext) (car x-ext) (cdr y-ext)))
           (new-stil (ly:stencil-translate-axis
                         (ly:stencil-combine-at-edge
                           stil
                           X LEFT
                           line-stil 0)
                             (* 0.5 thick) X)))
    new-stil))

#(define (splayed-stem-stencil grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((pc (ly:grob-parent (ly:grob-parent grob X) X))
           (nc (ly:grob-parent grob Y))
           (dir (ly:grob-property grob 'direction))
           (half-space (* 0.5 (ly:staff-symbol-staff-space grob)))
           (thick (* (ly:grob-property grob 'thickness)
                     (ly:staff-symbol-line-thickness grob)))
           (default-stil (ly:stem::print grob))
           (default-stil-ext (ly:stencil-extent default-stil Y))
           (beam (ly:grob-object grob 'beam))
           (beam-corr (if (or (= dir 1) (ly:grob? beam)) 0 (* 4 thick)))
           (y1 (- (* half-space 2 ((if (= dir 1) car cdr) default-stil-ext)) 0))
           (y2 (- (* half-space (ly:stem::calc-stem-end-position grob)) 0))
           (nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (flag-stil (new-flag-stencil grob))
           (x (ly:grob-relative-coordinate (car nh) pc X))
           (first-nh-staff-pos (ly:grob-property (car nh) 'staff-position))
           (targets-staff-pos (map (lambda (x) (ly:grob-property x 'staff-position)) nh))
           (sorted-targets-staff-pos (sort targets-staff-pos <))
           (corr-add (if (and (>= first-nh-staff-pos (car sorted-targets-staff-pos)) (= dir 1))
                       (/ (- first-nh-staff-pos (car sorted-targets-staff-pos)) 2)
                       (/ (- first-nh-staff-pos (car (reverse sorted-targets-staff-pos))) 2)))
           (stem-y-corr (map (lambda (x)  (+  (/ (- x first-nh-staff-pos) 2) corr-add)) targets-staff-pos))
           (stencil (apply
                      ly:stencil-add
                      (map (lambda (nh y)
                             (let ((my-x (car (ly:grob-extent nh pc X))))
                               (make-line-stencil thick x y2 my-x (+  y y1))))
                           nh stem-y-corr))))
                           
   (if (and (>= (ly:grob-property grob 'duration-log) 3) (not (ly:grob? beam)))
     (ly:stencil-combine-at-edge
    stencil
    Y
    (if (= dir 1) UP DOWN)
    flag-stil
    (* -3 thick))
      stencil))))
   
#(define (new-X-extent grob)
;; TODO Better spacing
  (let* ((x-ext (ly:grob-property grob 'X-extent)))
  (ly:grob-set-property! grob 'X-extent (cons (* 2 (car x-ext)) (* 2 (cdr x-ext))))))
 
splayedStemChord =
#(define-music-function (parser location l1 l2 mus)
   (list? list? ly:music?)
#{
        \once \override Stem #'flag = #new-flag-stencil
        \once \override Score.NoteColumn #'before-line-breaking = #new-X-extent
        \once \override Stem #'positioning-done = #(positioning-done $l1 $l2)
        \once \override Stem #'stencil = #splayed-stem-stencil
       
        \once \override Score.Script #'after-line-breaking =
          #(lambda (grob)
             (let* ((note-head (ly:grob-parent grob X))
                    (nc (ly:grob-parent note-head X))
                    (nh (ly:grob-array->list (ly:grob-object nc 'note-heads))))
               (set! (ly:grob-parent grob X)
                     (car nh))))   
         $mus
#})
 
%%%%%%%%%%% test %%%%%%%%%%%%%%%%%%%%%%%%%%%

m¹ = \relative c {
         \clef bass
         \voiceOne
         c4
         \splayedStemChord
         % Note-head-offsets. Note: elements are multipliers.
           #'(0 -4 3.5 -2.5 0.9 0 1.6)
         % Accidental-offsets, elements are added to the calculated values.
           #'(0 0 0 0 0 1 0)
         <b,! dis bes f'! d! d! gis>8
         
         d'8 e f! g a
}

m² = \relative c {
         \clef bass
         \voiceTwo
         c4
         \once \override Beam #'positions = #'(-9 . -5.5)
         \splayedStemChord
           #'(0 -4 3.5 -2.5 0.9 0 1.6)
           #'(0  0 0    0   0   1 0)
         <b,! dis bes f'! d! d! gis>8
         
         d'8 e f! g a
}

m³ = \relative c, {
  \clef bass
  #(set-accidental-style 'forget)

  <c! cis d es g>4
  \repeat unfold 2 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>8-.--
          \noBeam
  }
  \voiceTwo
  \repeat unfold 4 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>
          \noBeam
  }
  \oneVoice
  \repeat unfold 4 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(0 0 0 0 0)
          <c! cis d es g>
  }
  \voiceTwo
  \repeat unfold 4 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(0 0 0 0 0)
          <c! cis d es g>
  }
}

\score {
        \new StaffGroup <<
          \new Staff \with { instrumentName = "One Voice" }
            { \m¹ \m² }
         
          \new Staff \with {
            instrumentName = "Two Voices"
            \override VerticalAxisGroup #'staff-staff-spacing =
#'((basic-distance . 10)
   (minimum-distance . 10)
   (padding . 4)
   (stretchability . 100))
          }
            \repeat unfold 2 {
            <<
            \new Voice \transpose c c'\m¹
            \new Voice \m²
            >>
            }
           
          \new Staff \with {
            instrumentName = "kilgore's chord "
            \override VerticalAxisGroup #'staff-staff-spacing =
#'((basic-distance . 10)
   (minimum-distance . 12)
   (padding . 4)
   (stretchability . 100))
          }
            \m³
         
          \new Staff \with { instrumentName = "control" }
            \relative c' { \clef bass  \repeat unfold 8 { r4 } }
        >>
        \header {
        dedication = \markup {
                \center-column {
                "Thanks to Mike Solomon"
                \line { see \with-url #"http://lists.gnu.org/archive/html/lilypond-user/2011-12/msg00421.html" \italic "this thread" }
                \vspace #1
                }
        }
        title = \markup {
                \center-column {
                "Complex chords"
                "with"
                "splayed stems"
                \vspace #2
                }
        }
        }
}

und eine verbesserte Fassung für "2.15.39". Aus irgendeinem mir unerklärlichem Grund funktioniert es für "2.15.41"  allerdings nicht, wohl aber mit "2.15.42"

\version "2.15.39"

\paper {
        indent = 25
        print-all-headers = ##t
}

#(define ((positioning-done l1 l2) grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (default-nh-x-width (interval-length (ly:stencil-extent (ly:note-head::print grob) X)))
           (accidental-grobs (map (lambda (x) (ly:grob-object x 'accidental-grob)) nh))
           (sys (ly:grob-parent (ly:grob-parent (ly:grob-parent grob X) X) X))
           (nh-ref-pts (map (lambda (x) (ly:grob-relative-coordinate x sys X)) nh))
           (acc-ref-pts
             (map
               (lambda (x) (if (ly:grob? x) (ly:grob-relative-coordinate x sys X) #f))
                 accidental-grobs)))

  ;; note-heads
      (for-each
        (lambda (x y z)
          (ly:grob-translate-axis! x (* y z) X))
            nh (iota (length nh)) l1)
       
  ;; accidentals
      (for-each
        (lambda (a b c d add)
    (if (null? a)
      #f
                  (ly:grob-translate-axis! a (- (* b c) d default-nh-x-width add) X)))
          accidental-grobs (iota (length nh)) l1 acc-ref-pts l2)))
    0.0)

#(define (splayed-stem-stencil grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((pc (ly:grob-parent (ly:grob-parent grob X) X))
           (nc (ly:grob-parent grob Y))
           (dir (ly:grob-property grob 'direction))
           (half-space (* 0.5 (ly:staff-symbol-staff-space grob)))
           (thick (* (ly:grob-property grob 'thickness)
                     (ly:staff-symbol-line-thickness grob)))
           (y1 (* half-space (ly:stem::calc-stem-begin-position grob)))
           (y2 (- (* half-space (ly:stem::calc-stem-end-position grob)) (* 2 thick)))
           (nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (x (ly:grob-relative-coordinate (car nh) pc X))
           (first-nh-staff-pos (ly:grob-property (car nh) 'staff-position))
           (targets-staff-pos (map (lambda (x) (ly:grob-property x 'staff-position)) nh))
           (sorted-targets-staff-pos (sort targets-staff-pos <))
           (beam (ly:grob-object grob 'beam))
           (beam-corr (if (and (= dir -1) (ly:grob? beam)) -1 1))
           (corr-add (if (and (>= first-nh-staff-pos (car sorted-targets-staff-pos)) (= dir 1))
                       (/ (- first-nh-staff-pos (car sorted-targets-staff-pos)) 2)
                       (/ (- first-nh-staff-pos (car (reverse sorted-targets-staff-pos))) 2)))
           (stem-y-corr (map (lambda (x)  (+  (/ (- x first-nh-staff-pos) 2) corr-add)) targets-staff-pos))
           (stencil (apply
                      ly:stencil-add
                      (map (lambda (nh y)
                             (let ((my-x (car (ly:grob-extent nh pc X))))
                               (make-line-stencil thick x (* beam-corr y2) my-x (+  y y1))))
                           nh stem-y-corr))))
    stencil)))

#(define (new-flag-stencil grob)
    (let* ((stil (ly:flag::print grob))
           (stem (ly:grob-parent grob X))
           (dir (ly:grob-property stem 'direction))
           (thick (* (ly:grob-property stem 'thickness)
             (ly:staff-symbol-line-thickness grob)))
           (x-ext (ly:stencil-extent stil X))
           (y-ext (ly:stencil-extent stil Y))
           (line-stil (make-line-stencil thick (car x-ext) (car y-ext) (car x-ext) (cdr y-ext)))
           (new-stil (ly:stencil-translate-axis
                         (ly:stencil-combine-at-edge
                           stil
                           X LEFT
                           line-stil 0)
                             (* dir (- (interval-length y-ext) (* 3 thick))) Y)))
    new-stil))
   
#(define (new-X-extent grob)
;; TODO Better spacing
  (let* ((x-ext (ly:grob-property grob 'X-extent)))
  (ly:grob-set-property! grob 'X-extent (cons (* 2 (car x-ext)) (* 2 (cdr x-ext))))))
   
splayedStemChord =
#(define-music-function (parser location l1 l2 mus)
   (list? list? ly:music?)
#{
        \once \override Flag #'stencil = #new-flag-stencil
        \once \override Score.NoteColumn #'before-line-breaking = #new-X-extent
        \once \override Stem #'positioning-done = #(positioning-done l1 l2)
        \once \override Stem #'stencil = #splayed-stem-stencil
       
        \once \override Score.Script #'after-line-breaking =
          #(lambda (grob)
             (let* ((note-head (ly:grob-parent grob X))
                    (nc (ly:grob-parent note-head X))
                    (nh (ly:grob-array->list (ly:grob-object nc 'note-heads))))
               (set! (ly:grob-parent grob X)
                     (car nh))))
                 
         $mus

#})
 
%%%%%%%%%%% test %%%%%%%%%%%%%%%%%%%%%%%%%%%

m¹ = \relative c {
         \clef bass
         \voiceOne
         c4
         \splayedStemChord
         % Note-head-offsets. Note: elements are multipliers.
           #'(0 -4 3.5 -2.5 0.9 0 1.6)
         % Accidental-offsets, elements are added to the calculated values.
           #'(0 0 0 0 0 1 0)
         <b,! dis bes f'! d! d! gis>8
         
         d'8 e f! g a
}

m² = \relative c {
         \clef bass
         \voiceTwo
         c4
         \once \override Beam #'positions = #'(-9 . -3.5)
         \splayedStemChord
           #'(0 -4 3.5 -2.5 0.9 0 1.6)
           #'(0  0 0    0   0   1 0)
         <b,! dis bes f'! d! d! gis>8
         
         d'8 e f! g a
}

m³ = \relative c, {
  \clef bass
  \accidentalStyle "forget"
 
  <c! cis d es g>
  \repeat unfold 3 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>
          \noBeam
  }
  \voiceTwo
  \repeat unfold 4 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>
          \noBeam
  }
  \oneVoice
  \repeat unfold 8 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(0 0 0 0 0)
          <c! cis d es g>
  }
}

\score {
        \new StaffGroup <<
          \new Staff \with { instrumentName = "One Voice" }
            { \m¹ \m² }
         
          \new Staff \with { instrumentName = "Two Voices" }
            \repeat unfold 2 {
            <<
            \new Voice \transpose c c'\m¹
            \new Voice \m²
            >>
            }
           
          \new Staff \with { instrumentName = "kilgore's chord " }
            \m³
         
          \new Staff \with { instrumentName = "control" }
            \relative c' { \clef bass  \repeat unfold 8 { r4 } }
        >>
        \header {
        dedication = \markup {
                \center-column {
                "Thanks to Mike Solomon"
                \line { see \with-url #"http://lists.gnu.org/archive/html/lilypond-user/2011-12/msg00421.html" \italic "this thread" }
                \vspace #1
                }
        }
        title = \markup {
                \center-column {
                "Complex chords"
                "with"
                "splayed stems"
                \vspace #2
                }
        }
        }
}

Gruß,
  Harm

kilgore

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #5 am: Montag, 30. Juli 2012, 11:08 »
Wow das ist ja was neues! Wirklich super, danke Harm (und danke Mike!).

Unten siehst du meine "beste Lösung" für das Akkord. Ich finde es eigentlich nur nötig einen Notenkopf zu verstellen mit dem \splayedStemChord, deshalb auch ein \tweak für das D mittendrin.

Ein Problem ist aber aufgetaucht....in dem Stück nutze ich #modern-straight-flag, was von dem \splayedStemChord aufgehoben wird. Kriegt man es auch mit dem gewünschten Fähnchen hin?

Viele Grüße!
kil

update: habe vergessen mein Code mit einzutragen!


\version "2.14.2"

#(define ((positioning-done l1 l2) grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (default-nh-x-width (interval-length (ly:stencil-extent (ly:note-head::print grob) X)))
           (accidental-grobs (map (lambda (x) (ly:grob-object x 'accidental-grob)) nh))
           (sys (ly:grob-parent (ly:grob-parent (ly:grob-parent grob X) X) X))
           (nh-ref-pts (map (lambda (x) (ly:grob-relative-coordinate x sys X)) nh))
           (acc-ref-pts
             (map
               (lambda (x) (if (ly:grob? x) (ly:grob-relative-coordinate x sys X) #f))
                 accidental-grobs)))

  ;; note-heads
      (for-each
        (lambda (x y z)
          (ly:grob-translate-axis! x (* y z) X))
            nh (iota (length nh)) l1)
       
  ;; accidentals
      (for-each
        (lambda (a b c d add)
    (if (null? a)
      #f
                  (ly:grob-translate-axis! a (- (* b c) d default-nh-x-width add) X)))
          accidental-grobs (iota (length nh)) l1 acc-ref-pts l2)))
    0.0)
   
#(define (new-flag-stencil grob)
    (let* ((stil (ly:stem::calc-flag grob))
           (nc (ly:grob-parent grob X))
           (dir (ly:grob-property grob 'direction))
           (thick (* (ly:grob-property grob 'thickness)
             (ly:staff-symbol-line-thickness grob)))
           (x-ext (ly:stencil-extent stil X))
           (y-ext (ly:stencil-extent stil Y))
           (line-stil (make-line-stencil thick (car x-ext) (car y-ext) (car x-ext) (cdr y-ext)))
           (new-stil (ly:stencil-translate-axis
                         (ly:stencil-combine-at-edge
                           stil
                           X LEFT
                           line-stil 0)
                             (* 0.5 thick) X)))
    new-stil))

#(define (splayed-stem-stencil grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((pc (ly:grob-parent (ly:grob-parent grob X) X))
           (nc (ly:grob-parent grob Y))
           (dir (ly:grob-property grob 'direction))
           (half-space (* 0.5 (ly:staff-symbol-staff-space grob)))
           (thick (* (ly:grob-property grob 'thickness)
                     (ly:staff-symbol-line-thickness grob)))
           (default-stil (ly:stem::print grob))
           (default-stil-ext (ly:stencil-extent default-stil Y))
           (beam (ly:grob-object grob 'beam))
           (beam-corr (if (or (= dir 1) (ly:grob? beam)) 0 (* 4 thick)))
           (y1 (- (* half-space 2 ((if (= dir 1) car cdr) default-stil-ext)) 0))
           (y2 (- (* half-space (ly:stem::calc-stem-end-position grob)) 0))
           (nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (flag-stil (new-flag-stencil grob))
           (x (ly:grob-relative-coordinate (car nh) pc X))
           (first-nh-staff-pos (ly:grob-property (car nh) 'staff-position))
           (targets-staff-pos (map (lambda (x) (ly:grob-property x 'staff-position)) nh))
           (sorted-targets-staff-pos (sort targets-staff-pos <))
           (corr-add (if (and (>= first-nh-staff-pos (car sorted-targets-staff-pos)) (= dir 1))
                       (/ (- first-nh-staff-pos (car sorted-targets-staff-pos)) 2)
                       (/ (- first-nh-staff-pos (car (reverse sorted-targets-staff-pos))) 2)))
           (stem-y-corr (map (lambda (x)  (+  (/ (- x first-nh-staff-pos) 2) corr-add)) targets-staff-pos))
           (stencil (apply
                      ly:stencil-add
                      (map (lambda (nh y)
                             (let ((my-x (car (ly:grob-extent nh pc X))))
                               (make-line-stencil thick x y2 my-x (+  y y1))))
                           nh stem-y-corr))))
                           
   (if (and (>= (ly:grob-property grob 'duration-log) 3) (not (ly:grob? beam)))
     (ly:stencil-combine-at-edge
    stencil
    Y
    (if (= dir 1) UP DOWN)
    flag-stil
    (* -3 thick))
      stencil))))
   
#(define (new-X-extent grob)
;; TODO Better spacing
  (let* ((x-ext (ly:grob-property grob 'X-extent)))
  (ly:grob-set-property! grob 'X-extent (cons (* 2 (car x-ext)) (* 2 (cdr x-ext))))))
 
splayedStemChord =
#(define-music-function (parser location l1 l2 mus)
   (list? list? ly:music?)
#{
        \once \override Stem #'flag = #new-flag-stencil
        \once \override Score.NoteColumn #'before-line-breaking = #new-X-extent
        \once \override Stem #'positioning-done = #(positioning-done $l1 $l2)
        \once \override Stem #'stencil = #splayed-stem-stencil
       
        \once \override Score.Script #'after-line-breaking =
          #(lambda (grob)
             (let* ((note-head (ly:grob-parent grob X))
                    (nc (ly:grob-parent note-head X))
                    (nh (ly:grob-array->list (ly:grob-object nc 'note-heads))))
               (set! (ly:grob-parent grob X)
                     (car nh))))   
         $mus
#})

\relative c, {
  \clef bass
  \override Score.Stem #'flag = #modern-straight-flag
  \splayedStemChord #'( 0 3.7 0 0 0 ) #'( 1 -.1 0 0 0 )
  <c! cis \tweak #'extra-offset #'( 1.2 . 0 ) d es g>8
  s4
  <c! cis! d es! g>8
  s4
  <bis cis! d es! g>8
  s4
  \splayedStemChord #'( 0 3.7 0 0 0 ) #'( 1 -.1 0 0 0 )
  <c! cis \tweak #'extra-offset #'( 1.2 . 0 ) d es g>8~
  \splayedStemChord #'( 0 3.7 0 0 0 ) #'( 1 -.1 0 0 0 )
  <c cis \tweak #'extra-offset #'( 1.2 . 0 ) d es g>2
}
« Letzte Änderung: Montag, 30. Juli 2012, 13:37 von kilgore »

trulli

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #6 am: Montag, 30. Juli 2012, 12:08 »
Meine Güte harm - ist ja nicht zu glauben, was Lily so kann.   :o

Sieht aus wie moderne Kunst...  :)

Hier noch ein kleiner Nachtrag für die Cluster-Notation, wie sie in den Penderecki-Partituren verwendet wird. Ich denke aber, dass die Lösung von harm am besten ist, weil die Cluster-Notation keine Tonlängen darstellen kann.

\version "2.14.0"
\relative c, {
  \clef bass
  <bis cis d es g>1
  <<
    { \makeClusters { <c g'>2 <c g'>} }
    \new Staff
   \with { \remove "Time_signature_engraver"
              fontSize = #-2
              \override StaffSymbol #'staff-space = #(magstep -2)
              \override StaffSymbol #'thickness = #(magstep -2)
              firstClef = ##t }
    { \clef bass \autoBeamOff
      \override Stem #'transparent =  ##t
        c16 cis  d es  g  }
  >>
s
}

Gruß von Trulli

chf

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #7 am: Montag, 30. Juli 2012, 12:58 »
Hallo Freunde,

das ist ja fantastisch!
Als ich meine Fragen dazu gestellt habe, war ich ein bisschen zu früh für diese tollen Bilder.
Manchmal ist es ein Glück, wenn es beim Verlag nicht so schnell geht - so komme ich mit der neuen Variante noch zurecht...

Gruß
chf

harm6

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #8 am: Montag, 30. Juli 2012, 18:43 »
Hallo zusammen,

vielen Dank für die freundlichen Kommentare.

@kilgore
Hier eine Fassung, die auch andere Fähnchenstile berücksichtigt.

Ich habe `which-flag' definiert als das default-Fähnchen.
Willst Du mit \splayedStemChord ein anderes haben, so benutze #(set! which-flag modern-straight-flag) oder #(set! which-flag old-straight-flag). Der Befehl \override Score.Stem #'flag = #modern-straight-flag wird dadurch allerdings nicht überflüssig.

Eine alternative Vorgehensweise wäre, die Angabe mit in den Funktionsaufruf zu packen. Das hätte zu:
\splayedStemChord #modern-straight-flag #'( 0 3.7 0 0 0 ) #'( 1 -.1 0 0 0 )geführt. Aber das finde ich ehrlich gesagt zu unübersichtlich.

\version "2.14.2"

#(define ((positioning-done l1 l2) grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (default-nh-x-width (interval-length (ly:stencil-extent (ly:note-head::print grob) X)))
           (accidental-grobs (map (lambda (x) (ly:grob-object x 'accidental-grob)) nh))
           (sys (ly:grob-parent (ly:grob-parent (ly:grob-parent grob X) X) X))
           (nh-ref-pts (map (lambda (x) (ly:grob-relative-coordinate x sys X)) nh))
           (acc-ref-pts
             (map
               (lambda (x) (if (ly:grob? x) (ly:grob-relative-coordinate x sys X) #f))
                 accidental-grobs)))

  ;; note-heads
      (for-each
        (lambda (x y z)
          (ly:grob-translate-axis! x (* y z) X))
            nh (iota (length nh)) l1)
       
  ;; accidentals
      (for-each
        (lambda (a b c d add)
    (if (null? a)
      #f
                  (ly:grob-translate-axis! a (- (* b c) d default-nh-x-width add) X)))
          accidental-grobs (iota (length nh)) l1 acc-ref-pts l2)))
    0.0)
   
#(define (which-flag grob) (ly:stem::calc-flag grob))
   
#(define (new-flag-stencil grob)
  (if (< (ly:grob-property grob 'duration-log) 3)
    #f
    (let* ((stil (which-flag grob))
           (dir (ly:grob-property grob 'direction))
           (thick (* (ly:grob-property grob 'thickness)
             (ly:staff-symbol-line-thickness grob)))
           (X-corr (if (or (eq? (procedure-name which-flag) 'old-straight-flag)
                           (eq? (procedure-name which-flag) 'modern-straight-flag))
                     (* -0.5 thick)
                     0))
           (x-ext (ly:stencil-extent stil X))
           (y-ext (ly:stencil-extent stil Y))
           (line-stil (make-line-stencil thick (car x-ext) (car y-ext) (car x-ext) (cdr y-ext)))
           (new-stil (ly:stencil-translate-axis
                         (ly:stencil-combine-at-edge
                           (ly:stencil-translate-axis
                             stil
                             (* dir 0.5 thick) Y)
                           X LEFT
                           line-stil X-corr)
                             (* 0.5 thick) X)))
    new-stil)))

#(define (splayed-stem-stencil grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((pc (ly:grob-parent (ly:grob-parent grob X) X))
           (nc (ly:grob-parent grob Y))
           (dir (ly:grob-property grob 'direction))
           (half-space (* 0.5 (ly:staff-symbol-staff-space grob)))
           (thick (* (ly:grob-property grob 'thickness)
                     (ly:staff-symbol-line-thickness grob)))
           (default-stil (ly:stem::print grob))
           (default-stil-ext (ly:stencil-extent default-stil Y))
           (beam (ly:grob-object grob 'beam))
           (beam-corr (if (or (= dir 1) (ly:grob? beam)) 0 (* 4 thick)))
           (y1 (- (* half-space 2 ((if (= dir 1) car cdr) default-stil-ext)) 0))
           (y2 (- (* half-space (ly:stem::calc-stem-end-position grob)) 0))
           (nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (flag-stil (new-flag-stencil grob))
           (x (ly:grob-relative-coordinate (car nh) pc X))
           (first-nh-staff-pos (ly:grob-property (car nh) 'staff-position))
           (targets-staff-pos (map (lambda (x) (ly:grob-property x 'staff-position)) nh))
           (sorted-targets-staff-pos (sort targets-staff-pos <))
           (corr-add (if (and (>= first-nh-staff-pos (car sorted-targets-staff-pos)) (= dir 1))
                       (/ (- first-nh-staff-pos (car sorted-targets-staff-pos)) 2)
                       (/ (- first-nh-staff-pos (car (reverse sorted-targets-staff-pos))) 2)))
           (stem-y-corr (map (lambda (x)  (+  (/ (- x first-nh-staff-pos) 2) corr-add)) targets-staff-pos))
           (stencil (apply
                      ly:stencil-add
                      (map (lambda (nh y)
                             (let ((my-x (car (ly:grob-extent nh pc X))))
                               (make-line-stencil thick x y2 my-x (+  y y1))))
                           nh stem-y-corr))))
                           
   (if (and (>= (ly:grob-property grob 'duration-log) 3) (not (ly:grob? beam)))
     (ly:stencil-combine-at-edge
    stencil
    Y
    (if (= dir 1) UP DOWN)
    flag-stil
    (* -3 thick))
      stencil))))
   
#(define (new-X-extent grob)
;; TODO Better spacing
  (let* ((x-ext (ly:grob-property grob 'X-extent)))
  (ly:grob-set-property! grob 'X-extent (cons (* 2 (car x-ext)) (* 2 (cdr x-ext))))))
 
splayedStemChord =
#(define-music-function (parser location l1 l2 mus)
   (list? list? ly:music?)
#{
        \once \override Score.NoteColumn #'before-line-breaking = #new-X-extent
        \once \override Stem #'positioning-done = #(positioning-done $l1 $l2)
        \once \override Stem #'stencil = #splayed-stem-stencil
       
        \once \override Score.Script #'after-line-breaking =
          #(lambda (grob)
             (let* ((note-head (ly:grob-parent grob X))
                    (nc (ly:grob-parent note-head X))
                    (nh (ly:grob-array->list (ly:grob-object nc 'note-heads))))
               (set! (ly:grob-parent grob X)
                     (car nh))))   
         $mus
#})
 
%%%%%%%%%%% test %%%%%%%%%%%%%%%%%%%%%%%%%%%

#(set! which-flag modern-straight-flag)
%#(set! which-flag old-straight-flag)

\relative c, {
  \clef bass
  \override Score.Stem #'flag = #modern-straight-flag
  \splayedStemChord #'( 0 3.7 0 0 0 ) #'( 1 -.1 0 0 0 )
  <c! cis \tweak #'extra-offset #'( 1.2 . 0 ) d es g>8
  r4
  <c! cis! d es! g>8
  r4
  <bis cis! d es! g>8
  r8
   
  \splayedStemChord #'( 0 3.7 0 0 0 ) #'( 1 -.1 0 0 0 )
  <c! cis \tweak #'extra-offset #'( 1.2 . 0 ) d es g>8
  ~
  \splayedStemChord #'( 0 3.7 0 0 0 ) #'( 1 -.1 0 0 0 )
  <c cis \tweak #'extra-offset #'( 1.2 . 0 ) d es g>2
}

Eine "2.15."-Fassung für andere Fähnchen steht noch aus.

Ein generelles Problem gibt es natürlich. Nach dem ganze Geschiebe der Notenköpfe und Vorzeichen ist das Spacing nicht mehr immer gut. Hier habe ich aber noch keine Lösung gefunden, wenn man von manuellen Eingriffen mal absieht.
Auch die Ties verlaufen nicht immer optomal, wie man an kilgore's Beispiel gut beobachten kann.

Gruß,
  Harm

trulli

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #9 am: Dienstag, 31. Juli 2012, 17:34 »
Hallo Leute,

trotzdem ich immer noch schwer beeindruckt bin, muss ich mal eine Kritik anmelden: die Notation mit den gespreizten Hälsen finde ich bei vielen Versetzungszeichen nicht mehr gut lesbar (ich meine damit die vielen Überschneidungen zwischen Versetzungszeichen und Hälsen). Ich würde da doch eher zur traditionellen Notation tendieren.

Andererseits hat dieses Thema mal wieder unser goldenes Motto bestätigt: Lily kann alles.  8)

Grüße

harm6

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #10 am: Dienstag, 31. Juli 2012, 23:06 »
Zitat von: trulli
die Notation mit den gespreizten Hälsen finde ich bei vielen Versetzungszeichen nicht mehr gut lesbar (ich meine damit die vielen Überschneidungen zwischen Versetzungszeichen und Hälsen). Ich würde da doch eher zur traditionellen Notation tendieren.

Hallo trulli,

Du hast schon recht mit der Lesbarkeit; natürlich hatte ich auch einige extreme Beispiele benutzt, schon des Show-Effekts wegen.

Allerdings ist diese Notationsart durchaus üblich.
Im Anhang ein kleiner Ausschnitt aus "Danse Sauvage" von Leo Ornstein (1892 - 2002)(lt. Wikipedia, ich kann's kaum glauben) . Diese Partitur erschien erstmals 1915(!) bei Schott.
(Vollständige Partitur in etwas besserer Qualität hier.)

Auch bin ich mir sehr sicher diese Notation bei Villa-Lobos in den Etüden gesehen zu haben. Ich bin im Moment nicht zu Hause und kann somit nicht selbst meinen Notenschrank zu Rate ziehen,  vielleicht kannst Du mal schnell nachschauen.

@kilgore
Nach Deiner Anmerkung zu #modern-straight-flag hatte ich zunächst versucht mich noch mal richtig schlau zu machen und wollte die Doku und die Definition studieren. Die Definition war schnell ausgemacht aber ich habe weder im LM noch in der NR noch in der IR irgendeine Erwähnung gefunden - in Worten: gar keine.
Erwähnung nur hier:
LSR und /Documentation/snippets.
(Diese snippets sind identisch, da alle snippets mit einem doc-tag in /Documentation/snippets importiert werden.)
Sowie in den Regression-tests und obskure Erwähnungen in zwei span. bzw frz. files:
Documentation/es/texidocs/using-alternative-flag-styles.texidoc
Documentation/fr/texidocs/using-alternative-flag-styles.texidoc

Wie bist Du eigentlich drauf gestoßen? Übers LSR?


Gruß,
  Harm


kilgore

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #11 am: Dienstag, 31. Juli 2012, 23:33 »
@Trulli

Ja, die Lesbarkeit (und Ästhetic) finde ich nicht so optimal, aber manchmal ist es halt die einzige Lösung so ein Akkord darzustellen. Mann kann mit den Vorzeichen manchmal tricksen, dass es irgendwie so geht. Wenn man Klavier spielt und so ein Stück lernt, schaut man sowieso beim Aufführen die genaue Töne nicht mehr an - die liegen ja schon "in den Fingern".

In dem betroffenen Akkord finde ich das His aber irgendwie auch störend, obwohl es wohl wirklich die beste und "sinnvollste" Darstellung ist...ich tendiere jetzt dazu, das Akkord wie am Anfang einfach so zu lassen ( <c! cis d es g> ) mit einem kleinen Notiz um die genaue Töne zu nennen (eigentlich dein Idee). Das Akkord kommt oft in dem Stück, aber man braucht es nur einmal zu Erklären.

@Harm

Ich nutze die #modern-straight-flag eigentlich schon länger. Wo hab ich das her? Weiß ich gar nicht mehr! Bestimmt über LSR. Toll aber, dass es in der neuen Version ein Flag GROB gibt. Ich komme immer durcheinander mit Stem #'flag und Stem #'flag-style.

Gruß
kil

trulli

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #12 am: Mittwoch, 1. August 2012, 23:16 »
Hallo harm,

ja, ich habe tatsächlich mehrere Stellen in den Etüden gefunden. In der Nr. 4 auf der letzten Seite (in der Eschig Ausgabe) und dann noch in der Nr.12.
Kaum zu glauben - wo doch Lobos die Versetzungszeichen mitunter sehr beliebig und mehr in Bezug auf die Stimmführungen (als auf die Tonart) gesetzt hat. In dem Beispiel hätte ich eher von Anfang an ein "ais" erwartet, weil im Takt zuvor das "cis" auftaucht. Dann wäre der gespreizte Hals nicht nötig gewesen. Aber der Meister war eben eigen.  :)

Danke für den Hinweis! Übrigens: wie es sich für den schönen Notensatz von Eschig gehört, gibt es keine Überschneidungen zwischen Balken und Versetzungszeichen. Allerdings ist es auch nur eine einfache Spaltung.

Erwartungsgemäß habe ich in der Espiral Eterna von Brouwer (im letzten Akkord) auch einen gepreizten Hals entdeckt. Du hast Recht: es gibt da bestimmt noch viele Beispiele.

Gruß von Trulli

P.S.: Hört euch mal das Ornstein Stück bei YouTube an - das ist ja der Hammer....
« Letzte Änderung: Mittwoch, 1. August 2012, 23:28 von trulli »

kilgore

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #13 am: Freitag, 16. November 2012, 15:10 »
Hi Alle!

Ich möchte diese hervorragende Lösung auch im 2.16.0 nützen. Wie krieg ich das hin?

Danke!

Gruß
kil

harm6

  • Member
Re: komplexe Akkord - bessere Lösung?
« Antwort #14 am: Freitag, 16. November 2012, 22:53 »
Hallo kilgore,

Zitat von: kilgore
Ich möchte diese hervorragende Lösung auch im 2.16.0 nützen. Wie krieg ich das hin?

Leider funktioniert convert-ly hier nicht vollständig, da ich das Fähnchen neu konstruiert hatte. Zusammen mit der Änderung auf ein eigenes Flag-grob war das dann zuviel für convert-ly.

Ich hatte hier:

@kilgore
Hier eine Fassung, die auch andere Fähnchenstile berücksichtigt.

Ich habe `which-flag' definiert als das default-Fähnchen.
Willst Du mit \splayedStemChord ein anderes haben, so benutze #(set! which-flag modern-straight-flag) oder #(set! which-flag old-straight-flag). Der Befehl \override Score.Stem #'flag = #modern-straight-flag wird dadurch allerdings nicht überflüssig.

[...]

Eine "2.15."-Fassung für andere Fähnchen steht noch aus.

schon über andere Fähnchenstile geschrieben.

Um das ganze für 2.16 zugänglich zu machen, war dann eine partielle Neucodierung nötig.

Funktioniert jetzt aber für 2.16.0 und 2.17.6. Anwendung wie bisher.
Vorausgesetzt ich habe nicht irgendwo Unsinn gemacht, falls doch wirst Du Dich schon melden. :)

\version "2.16.0"

\paper {
        indent = 25
        print-all-headers = ##t
}

#(define ((positioning-done l1 l2) grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (default-nh-x-width (interval-length (ly:stencil-extent (ly:note-head::print grob) X)))
           (accidental-grobs (map (lambda (x) (ly:grob-object x 'accidental-grob)) nh))
           (sys (ly:grob-parent (ly:grob-parent (ly:grob-parent grob X) X) X))
           (nh-ref-pts (map (lambda (x) (ly:grob-relative-coordinate x sys X)) nh))
           (acc-ref-pts
             (map
               (lambda (x) (if (ly:grob? x) (ly:grob-relative-coordinate x sys X) #f))
                 accidental-grobs)))

  ;; note-heads
      (for-each
        (lambda (x y z)
          (ly:grob-translate-axis! x (* y z) X))
            nh (iota (length nh)) l1)
       
  ;; accidentals
      (for-each
        (lambda (a b c d add)
    (if (null? a)
      #f
                  (ly:grob-translate-axis! a (- (* b c) d default-nh-x-width add) X)))
          accidental-grobs (iota (length nh)) l1 acc-ref-pts l2)))
    0.0)

#(define (splayed-stem-stencil grob)
  (if (< (ly:grob-property grob 'duration-log) 1)
    #f
    (let* ((pc (ly:grob-parent (ly:grob-parent grob X) X))
           (nc (ly:grob-parent grob Y))
           (dir (ly:grob-property grob 'direction))
           (half-space (* 0.5 (ly:staff-symbol-staff-space grob)))
           (thick (* (ly:grob-property grob 'thickness)
                     (ly:staff-symbol-line-thickness grob)))
           (y1 (* half-space (ly:stem::calc-stem-begin-position grob)))
           (y2 (- (* half-space (ly:stem::calc-stem-end-position grob)) (* 2 thick)))
           (nh (ly:grob-array->list (ly:grob-object grob 'note-heads)))
           (x (ly:grob-relative-coordinate (car nh) pc X))
           (first-nh-staff-pos (ly:grob-property (car nh) 'staff-position))
           (targets-staff-pos (map (lambda (x) (ly:grob-property x 'staff-position)) nh))
           (sorted-targets-staff-pos (sort targets-staff-pos <))
           (beam (ly:grob-object grob 'beam))
           (beam-corr (if (and (= dir -1) (ly:grob? beam)) -1 1))
           (corr-add (if (and (>= first-nh-staff-pos (car sorted-targets-staff-pos)) (= dir 1))
                       (/ (- first-nh-staff-pos (car sorted-targets-staff-pos)) 2)
                       (/ (- first-nh-staff-pos (car (reverse sorted-targets-staff-pos))) 2)))
           (stem-y-corr (map (lambda (x)  (+  (/ (- x first-nh-staff-pos) 2) corr-add)) targets-staff-pos))
           (stencil (apply
                      ly:stencil-add
                      (map (lambda (nh y)
                             (let ((my-x (car (ly:grob-extent nh pc X))))
                               (make-line-stencil thick x (* beam-corr y2) my-x (+  y y1))))
                           nh stem-y-corr))))
    stencil)))
   
#(define (which-flag grob) (ly:flag::print grob))

#(define (new-flag-stencil grob)
    (let* ((stil (which-flag grob))
           (stem (ly:grob-parent grob X))
           (dir (ly:grob-property stem 'direction))
           (thick (* (ly:grob-property stem 'thickness)
                     (ly:staff-symbol-line-thickness grob)))
           (X-corr (if (or (eq? (procedure-name which-flag) 'old-straight-flag)
                           (eq? (procedure-name which-flag) 'modern-straight-flag))
                     (* -0.5 thick)
                     0))
           (Y-corr (cond ((eq? (procedure-name which-flag) 'old-straight-flag)
                          (* 0.66 thick))
                         ((eq? (procedure-name which-flag) 'modern-straight-flag)
                          (* 0.5 thick))
                         (else 0)))
           (x-ext (ly:stencil-extent stil X))
           (y-ext (ly:stencil-extent stil Y))
           (line-stil (make-line-stencil thick (car x-ext) (car y-ext) (car x-ext) (cdr y-ext)))
           (new-stil (ly:stencil-translate-axis
                         (ly:stencil-combine-at-edge
                           (ly:stencil-translate-axis
                           stil
                           (* dir Y-corr) Y)
                           X LEFT
                           line-stil
                           X-corr)
                             (* dir (- (interval-length y-ext) (* 2 dir thick)))
                             Y)))                       
    new-stil))
   
#(define (new-X-extent grob)
;; TODO Better spacing
  (let* ((x-ext (ly:grob-property grob 'X-extent)))
  (ly:grob-set-property! grob 'X-extent (cons (* 2 (car x-ext)) (* 2 (cdr x-ext))))))
   
splayedStemChord =
#(define-music-function (parser location l1 l2 mus)
   (list? list? ly:music?)
#{
        \once \override Flag #'stencil = #new-flag-stencil
        \once \override Score.NoteColumn #'before-line-breaking = #new-X-extent
        \once \override Stem #'positioning-done = #(positioning-done l1 l2)
        \once \override Stem #'stencil = #splayed-stem-stencil
       
        \once \override Score.Script #'after-line-breaking =
          #(lambda (grob)
             (let* ((note-head (ly:grob-parent grob X))
                    (nc (ly:grob-parent note-head X))
                    (nh (ly:grob-array->list (ly:grob-object nc 'note-heads))))
               (set! (ly:grob-parent grob X)
                     (car nh))))
                 
         $mus

#})
 
%%%%%%%%%%% test %%%%%%%%%%%%%%%%%%%%%%%%%%%

%#(set! which-flag old-straight-flag)
#(set! which-flag modern-straight-flag)


#(write (procedure-name which-flag))

m¹ = \relative c {
         \clef bass
         \voiceOne
         c4
         \splayedStemChord
         % Note-head-offsets. Note: elements are multipliers.
           #'(0 -4 3.5 -2.5 0.9 0 1.6)
         % Accidental-offsets, elements are added to the calculated values.
           #'(0 0 0 0 0 1 0)
         <b,! dis bes f'! d! d! gis>8
         
         d'8 e f! g a
}

m² = \relative c {
         \clef bass
         \voiceTwo
         c4
         \once \override Beam #'positions = #'(-9 . -3.5)
         \splayedStemChord
           #'(0 -4 3.5 -2.5 0.9 0 1.6)
           #'(0  0 0    0   0   1 0)
         <b,! dis bes f'! d! d! gis>8
         
         d'8 e f! g a
}

m³ = \relative c, {
  \clef bass
  \accidentalStyle "forget"
 
  <c! cis d es g>
  \repeat unfold 3 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>
          \noBeam
  }
  \voiceTwo
  \repeat unfold 4 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>
          \noBeam
  }
  \oneVoice
  \repeat unfold 8 {
          \splayedStemChord
            #'(0 -4.2 1.5 0 0)
            #'(1 0 0 0 0)
          <c! cis d es g>
  }
}

\score {
        \new StaffGroup <<
          \new Staff \with { instrumentName = "One Voice" }
            { \m¹ \m² }
         
          \new Staff \with { instrumentName = "Two Voices" }
            \repeat unfold 2 {
            <<
            \new Voice \transpose c c'\m¹
            \new Voice \m²
            >>
            }
           
          \new Staff \with { instrumentName = "kilgore's chord " }
            \m³
         
          \new Staff \with { instrumentName = "control" }
            \relative c' { \clef bass  \repeat unfold 8 { r4 } }
        >>
        \header {
        dedication = \markup {
                \center-column {
                "Thanks to Mike Solomon"
                \line { see \with-url #"http://lists.gnu.org/archive/html/lilypond-user/2011-12/msg00421.html" \italic "this thread" }
                \vspace #1
                }
        }
        title = \markup {
                \center-column {
                "Complex chords"
                "with"
                "splayed stems"
                \vspace #2
                }
        }
        }
}

Code auch im Anhang.

Gruß,
  Harm
« Letzte Änderung: Samstag, 17. November 2012, 03:41 von harm6 »