Deutschsprachiges LilyPond-Forum

Allgemeine Fragen und Probleme => Fragen und Probleme aller Art => Thema gestartet von: asmodeus am Sonntag, 31. Juli 2022, 20:27

Titel: Ornamente im Staff - Fragen zum Selbstbauversuch
Beitrag von: asmodeus am Sonntag, 31. Juli 2022, 20:27
Hallo zusammen,

ich setze gerade mal wieder Barockmusik und benoetige Ornamente (Pralltriller, Mordent), bei denen klar ist auf welche Note sie sich genau beziehen. Einfach oberhalb/unterhalb des Staff war mir nicht uebersichtlich genug, also ab damit in den Staff.

Erster Ansatz:

\version "2.22.2"
\absolute {
  \override Script.add-stem-support = ##t
  \override Script.side-axis = #0
  \override Script.direction = #1
  \override Script.X-offset = #3.2
  \override Script.Y-offset = #0

  % klappt gut
  a\prallprall
 
  % nicht mehr so...
  <a c' e>\prallprall\mordent
 
  % auch nicht so...
  <c'\prallprall e\mordent g>
}

Eine music function habe ich dafuer noch geschafft:

orpr =
#(define-music-function (music) (ly:music?)
  #{
  \once \override Script.add-stem-support = ##f
  \once \override Script.side-axis = #0
  \once \override Script.direction = #1
  \once \override Script.X-offset = #3.2
  \once \override Script.Y-offset = #0
  $music \prallprall
  #})

Aber lieber waere mir eine Event Function. prallprall ist definiert als:
prallprall = #(make-articulation 'prallprall)

Ansatz fuer Event Function:

\version "2.22.2"
evorpr = #(define-event-function () ()
#{
  -\tweak Script.add-stem-support ##f
  -\tweak Script.self-alignment-X #1
  -\tweak Script.side-axis #0
  -\tweak Script.direction #1
  -\tweak Script.X-offset #3.2
  -\tweak Script.Y-offset #0
  #(make-articulation 'prallprall)
#})

\absolute {
  a\evorpr
}

Leider bekomme ich dafuer eine failed assertion aus dem C++ Backend:

Starting lilypond 2.22.2 [Untitled (10)]...
Processing `/var/folders/y3/7yjff_xn62l5342f6flrnb600000gn/T/frescobaldi-8zu5p717/tmp_j6u80zb/document.ly'
Parsing...
Interpreting music...
warning: do not know how to interpret articulation:
warning:  scheme encoding:
Preprocessing graphical objects...Assertion failed: (scm_is_pair (s)), function get_stencil, file script-interface.cc, line 36.

Zwei Fragen dazu:
1. Welche tweaks koennten auch in Chords helfen? Wuerde ungerne manuell Y-offset tweaken...
2. Welcher Fehler ist mir bei der Event Function unterlaufen bzw. was koennte hier helfen? Die Definition von prallprall sieht ja so simpel aus...

Viele Gruesse,
Achim
Titel: Antw:Ornamente im Staff - Fragen zum Selbstbauversuch
Beitrag von: Arnold am Mittwoch, 3. August 2022, 08:55
Hallo asmodeus,

keine Lösung hier, sondern ein paar grundsätzliche Gedanken darüber.


Arnold
Titel: Antw:Ornamente im Staff - Fragen zum Selbstbauversuch
Beitrag von: harm6 am Donnerstag, 4. August 2022, 18:00
Hallo,

ich fand das 'ne ganz schön harte Nuss...

Schau mal, ob Du mit dem code klar kommst. Du brauchst allerdings eine neuere Lily-Version.

\version "2.23.9"

#(define script-at-side
  (lambda (grob)
    (let* ((side-axis (ly:grob-property grob 'side-axis)))
      (when (equal? X side-axis)
        (let* ((par-x (ly:grob-parent grob X))
               (par-y (ly:grob-parent grob Y))
               (dir (ly:grob-property grob 'direction))
               (nhd
                 (cond ((grob::has-interface par-x 'note-column-interface)
                         (car
                           (ly:grob-array->list
                             (ly:grob-object par-x 'note-heads))))
                       ((grob::has-interface par-x 'note-head-interface)
                         par-x)
                       ((grob::has-interface par-y 'note-head-interface)
                         par-y)
                       (else (ly:error "Need note-head as parent!"))))
               (nc (ly:grob-parent nhd X))
               (stem (ly:grob-object nc 'stem))
               (nhds (ly:grob-array->list (ly:grob-object nc 'note-heads)))
               (staff-pos (ly:grob-property nhd 'staff-position))
               (conditional-elts-array
                 (ly:grob-object nc 'conditional-elements #f))
               (conditional-elts
                 (if conditional-elts-array
                     (ly:grob-array->list conditional-elts-array)
                     '()))
               (acc-placement (ly:note-column-accidentals nc))
               (accs
                 (if (ly:grob? acc-placement)
                     (map cadr (ly:grob-object acc-placement 'accidental-grobs))
                     '()))
               (dot-col (ly:note-column-dot-column nc))
               (dots
                 (if (ly:grob? dot-col)
                     (ly:grob-array->list (ly:grob-object dot-col 'dots))
                     '())))

          (ly:grob-set-object! grob 'side-support-elements
            (ly:grob-list->grob-array
              (append
                (list stem)
                conditional-elts
                nhds
                accs
                dots)))

          (ly:grob-set-parent! grob Y nhd)

          (let* ((side-support-elements-x-ext
                  (ly:relative-group-extent
                    (ly:grob-object grob 'side-support-elements)
                    (ly:grob-common-refpoint grob nc X)
                    X))
                 (x-ext (ly:grob-extent grob grob X))
                 (script-row (ly:grob-object grob 'script-column #f))
                 (script-row-scripts-array
                   (if script-row
                       (ly:grob-object script-row 'scripts #f)
                       #f))
                 (script-row-scripts
                   (if script-row-scripts-array
                       (ly:grob-array->list script-row-scripts-array)
                       '()))
                 (already-offsetted
                   (filter
                     (lambda (sc)
                       (assoc-get
                         'x-offset-done
                         (ly:grob-property sc 'details)))
                     script-row-scripts))
                 (left-done
                   (filter
                     (lambda (sc)
                       (eqv? dir (ly:grob-property sc 'direction)))
                     already-offsetted))
                 (left-script-nc-ext
                   (reduce
                     interval-union
                     '(0 . 0)
                     (map
                       (lambda (sc) (ly:grob-extent sc nc X))
                       left-done)))
                 (right-done
                   (filter
                     (lambda (sc)
                       (eqv? dir (ly:grob-property sc 'direction)))
                     already-offsetted))
                 (right-script-nc-ext
                   (reduce
                     interval-union
                     '(0 . 0)
                     (map
                       (lambda (sc) (ly:grob-extent sc nc X))
                       right-done)))
                 (prev-x-coord
                   (cond ((and (pair? left-done) (eqv? dir -1))
                           (- (car left-script-nc-ext)
                              (car side-support-elements-x-ext)))
                         ((and (pair? right-done) (eqv? dir 1))
                           (- (cdr right-script-nc-ext)
                              (cdr side-support-elements-x-ext)))
                         (else 0)))
                 (x-off
                   (if (positive? dir)
                       (+
                          (cdr side-support-elements-x-ext)
                          (ly:grob-property grob 'padding)
                          (- (car (ly:grob-extent nhd nc X)))
                          (- (car x-ext)))
                       (-
                          (car side-support-elements-x-ext)
                          (ly:grob-property grob 'padding)
                          (car (ly:grob-extent nhd nc X))
                          (cdr x-ext)))))

            ;; debugging aid
            ;(ly:grob-set-property! grob 'color cyan)
            (ly:grob-set-property! grob 'Y-offset 0)
            (ly:grob-set-nested-property! grob '(details x-offset-done) #t)
            (ly:grob-set-property! grob 'X-offset (+ x-off prev-x-coord))))))))


\layout {
  \context {
    \Voice
    \override Script.padding = 0.5
  }
}

sideScript =
#(define-event-function (dir mus)(ly:dir? ly:music?)
#{
  \tweak before-line-breaking #script-at-side
  \tweak side-axis #X
  \tweak direction #dir
  $mus
#})

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Examples
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\paper { markup-markup-spacing.padding = 5 }

\header {
  title = \markup \rounded-box \fill-line { "Script left and right" }
}


%% Exp. 1
\score {
  {
    \time 3/8
    a'4.\sideScript #1 \prall
    a'4.\sideScript #-1 \prallprall
    a4\sideScript #-1 \prall
    a8\sideScript #1 \prallprall
  }
  \header {
    piece =
      \markup \override #'(line-width . 50) \wordwrap {
        Single notes, no event-chord, no Accidentals, i.e. no ScriptRow
        is created, a single Script is added left or right.
        Dots are respected.
      }
  }
}

%% Exp. 2
\score {
  {
    \time 2/8
    <a'>4\sideScript #1 \prall
    <a'> \sideScript #-1 \prallprall
    <a\sideScript #-1 \prall >
    <a\sideScript #1 \prallprall >
  }
  \header {
    piece =
      \markup \override #'(line-width . 50) \wordwrap {
        Single notes in event-chord, no Accidentals, no ScriptRow is created,
        a single Script is added left or right in- resp. outside of the
        event-chord.
      }
  }
}

%% Exp. 3
\score {
  {
    \time 2/8
    <ais'>4\sideScript #1 \prall
    a'! \sideScript #-1 \prallprall
    \time 3/8
    <aes\sideScript #-1 \prall >4.
    a!\sideScript #1 \prallprall
  }
  \header {
    piece =
      \markup \override #'(line-width . 50) \wordwrap {
        Single notes with and without event chord, Accidentals are present, i.e.
        ScriptRow \bold is created, a single Script is added left or right
        in- resp. outside of the event-chord.
      }
  }
}

%% Exp. 4
\score {
  {
    \set fingeringOrientations = #'(left)
    \set stringNumberOrientations = #'(right)
    \set strokeFingerOrientations = #'(up)

    \override StringNumber.X-align-on-main-noteheads = ##t
    \override StrokeFinger.X-align-on-main-noteheads = ##t

    \cadenzaOn
    <
     ais
         \sideScript #1 \prall
         -1
         \3
         \rightHandFinger #1
         \sideScript #-1 \mordent
    >4

    %% Fix overlap at BarLine
    \override Staff.BarLine.extra-spacing-height = #'(-inf.0 . +inf.0)
    \bar "||"

    \set stringNumberOrientations = #'(left up down)
    <
     aes'
         -1
         -2
         \3
         \rightHandFinger #2
         \sideScript #-1 \prallprall
     bes'
         \sideScript #1 \mordent
         \tweak extra-offset #'(5 . 1) -3
         -\tweak script-priority #0 \4
         \rightHandFinger #3
    >4.
       \arpeggio
       _> \upbow _\mordent \turn

    %% Fix overlap at BarLine
    \override Staff.BarLine.extra-spacing-height = #'(-inf.0 . +inf.0)
    \bar "||"

    <
      aes
        \sideScript #-1 \prallprall
        \sideScript #-1 \turn
        \sideScript #-1 \prallmordent

        \sideScript #1 \mordent
        \sideScript #1 \prall
        \sideScript #1 \upmordent
      \3
    >4...
    <
      a'!
        \sideScript #-1 \prallprall
        \sideScript #-1 \turn
        %% Fix other overlap
        \tweak extra-spacing-width #'(-11 . 0)
        \sideScript #-1 \prallmordent
      \3
    >4
    \bar "|."
  }
  \header {
    piece =
      \markup \override #'(line-width . 50) \wordwrap {
        Extreme.
      }
  }
}

Wahrscheinlich ist er noch nicht bug-frei, ergibt aber :

(http://i.imgur.com/LLGTIQJ.png) (https://imgur.com/LLGTIQJ)

Code ist auch angehängt.

Gruß,
  Harm


script-in-script-row-02.ly
Titel: Antw:Ornamente im Staff - Fragen zum Selbstbauversuch
Beitrag von: harm6 am Sonntag, 7. August 2022, 13:44
Hier noch eine deutlich vereinfachte Fassung:

\version "2.23.9"

#(define script-at-side
  (lambda (grob)
    (let* ((side-axis (ly:grob-property grob 'side-axis)))
      (when (equal? X side-axis)
        (let* ((par-x (ly:grob-parent grob X))
               (par-y (ly:grob-parent grob Y))
               (dir (ly:grob-property grob 'direction))
               (nhd
                 (cond ((grob::has-interface par-x 'note-column-interface)
                         (car
                           (ly:grob-array->list
                             (ly:grob-object par-x 'note-heads))))
                       ((grob::has-interface par-x 'note-head-interface)
                         par-x)
                       ((grob::has-interface par-y 'note-head-interface)
                         par-y)
                       (else (ly:error "Need note-head as parent!"))))
               (nc (ly:grob-parent nhd X))
               (stem (ly:grob-object nc 'stem))
               (nhds (ly:grob-array->list (ly:grob-object nc 'note-heads)))
               (conditional-elts-array
                 (ly:grob-object nc 'conditional-elements #f))
               (conditional-elts
                 (if conditional-elts-array
                     (ly:grob-array->list conditional-elts-array)
                     '()))
               (acc-placement (ly:note-column-accidentals nc))
               (accs
                 (if (ly:grob? acc-placement)
                     (map cadr (ly:grob-object acc-placement 'accidental-grobs))
                     '()))
               (dot-col (ly:note-column-dot-column nc))
               (dots
                 (if (ly:grob? dot-col)
                     (ly:grob-array->list (ly:grob-object dot-col 'dots))
                     '())))

          (ly:grob-set-object! grob 'side-support-elements
            (ly:grob-list->grob-array
              (append
                (list stem)
                conditional-elts
                nhds
                accs
                dots)))

          (ly:grob-set-parent! grob Y nhd)

          (let* ((script-row (ly:grob-object grob 'script-column #f))
                 (script-row-scripts-array
                   (if script-row
                       (ly:grob-object script-row 'scripts #f)
                       #f))
                 (script-row-scripts
                   (if script-row-scripts-array
                       (ly:grob-array->list script-row-scripts-array)
                       '()))
                 (already-offsetted
                   (filter
                     (lambda (sc)
                       (assoc-get
                         'x-offset-done
                         (ly:grob-property sc 'details)))
                     script-row-scripts))
                 (left-done
                   (filter
                     (lambda (sc)
                       (eqv? dir (ly:grob-property sc 'direction)))
                     already-offsetted))
                 (right-done
                   (filter
                     (lambda (sc)
                       (eqv? dir (ly:grob-property sc 'direction)))
                     already-offsetted)))


            (ly:grob-set-object! grob 'side-support-elements
              (ly:grob-list->grob-array
                (append
                  left-done
                  right-done
                  (ly:grob-array->list
                    (ly:grob-object grob 'side-support-elements)))))

              ;; debugging aid
              ;(ly:grob-set-property! grob 'color cyan)
              (ly:grob-set-property! grob 'Y-offset 0)
              (ly:grob-set-nested-property! grob '(details x-offset-done) #t)
              (ly:grob-set-property! grob 'X-offset
                ly:side-position-interface::x-aligned-side)))))))


\layout {
  \context {
    \Voice
    \override Script.padding = 0.5
  }
}

sideScript =
#(define-event-function (dir mus)(ly:dir? ly:music?)
#{
  \tweak before-line-breaking #script-at-side
  \tweak side-axis #X
  \tweak direction #dir
  $mus
#})

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Examples
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\paper { markup-markup-spacing.padding = 5 }

\header {
  title = \markup \rounded-box \fill-line { "Script left and right" }
}


%% Exp. 1
\score {
  {
    \time 3/8
    a'4.\sideScript #1 \prall
    a'4.\sideScript #-1 \prallprall
    a4\sideScript #-1 \prall
    a8\sideScript #1 \prallprall
  }
  \header {
    piece =
      \markup \override #'(line-width . 50) \wordwrap {
        Single notes, no event-chord, no Accidentals, i.e. no ScriptRow
        is created, a single Script is added left or right.
        Dots are respected.
      }
  }
}

%% Exp. 2
\score {
  {
    \time 2/8
    <a'>4\sideScript #1 \prall
    <a'> \sideScript #-1 \prallprall
    <a\sideScript #-1 \prall >
    <a\sideScript #1 \prallprall >
  }
  \header {
    piece =
      \markup \override #'(line-width . 50) \wordwrap {
        Single notes in event-chord, no Accidentals, no ScriptRow is created,
        a single Script is added left or right in- resp. outside of the
        event-chord.
      }
  }
}

%% Exp. 3
\score {
  {
    \time 2/8
    <ais'>4\sideScript #1 \prall
    a'! \sideScript #-1 \prallprall
    \time 3/8
    <aes\sideScript #-1 \prall >4.
    a!\sideScript #1 \prallprall
  }
  \header {
    piece =
      \markup \override #'(line-width . 50) \wordwrap {
        Single notes with and without event chord, Accidentals are present, i.e.
        ScriptRow \bold is created, a single Script is added left or right
        in- resp. outside of the event-chord.
      }
  }
}

%% Exp. 4
\score {
  {
    \set fingeringOrientations = #'(left)
    \set stringNumberOrientations = #'(right)
    \set strokeFingerOrientations = #'(up)

    \override StringNumber.X-align-on-main-noteheads = ##t
    \override StrokeFinger.X-align-on-main-noteheads = ##t

    \cadenzaOn
    <
     ais
         \sideScript #1 \prall
         -1
         \3
         \rightHandFinger #1
         \sideScript #-1 \mordent
    >4

    %% Fix overlap at BarLine
    \override Staff.BarLine.extra-spacing-height = #'(-inf.0 . +inf.0)
    \bar "||"

    \set stringNumberOrientations = #'(left up down)
    <
     aes'
         -1
         -2
         \3
         \rightHandFinger #2
         \sideScript #-1 \prallprall
     bes'
         \sideScript #1 \mordent
         \tweak extra-offset #'(5 . 1) -3
         -\tweak script-priority #0 \4
         \rightHandFinger #3
    >4.
       \arpeggio
       _> \upbow _\mordent \turn

    %% Fix overlap at BarLine
    \override Staff.BarLine.extra-spacing-height = #'(-inf.0 . +inf.0)
    \bar "||"

    <
      aes
        \sideScript #-1 \prallprall
        \sideScript #-1 \turn
        \sideScript #-1 \prallmordent

        \sideScript #1 \mordent
        \sideScript #1 \prall
        \sideScript #1 \upmordent
      \3
      bis
    >4...
    <
      a'!
        \sideScript #-1 \prallprall
        \sideScript #-1 \turn
        %% Fix other overlap
        \tweak extra-spacing-width #'(-11 . 0)
        \sideScript #-1 \prallmordent
      \3
      bes'
    >4
    \bar "|."
  }
  \header {
    piece =
      \markup \override #'(line-width . 50) \wordwrap {
        Extreme.
      }
  }
}

Ist auch wieder angehängt.

Gruß,
  Harm

script-in-script-row-03.ly