Ornamente im Staff - Fragen zum Selbstbauversuch

Begonnen von asmodeus, Sonntag, 31. Juli 2022, 20:27

« vorheriges - nächstes »

asmodeus

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

Arnold

Hallo asmodeus,

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

  • Bis zu zwei Noten in der Notenzeile wäre einfach, denn dann schreibt man eines oberhalb, das andere unterhalb.
  • Mit unterschiedlichen Farben für die Paarungen Notenkopf und Ornament käme man auch nicht viel weiter.
  • Direkt vor der Note muß der Platz von eventuell vorhandenen Vorzeichen und die rechts-links-Verschiebung falls zwei Notenköpfe eine Sekunde entfernt sind berücksichtigt werden
  • Objekte im Notensatz, welche (je nach Einstellung) links von den Noten platziert werden können, sind die Finger-Angaben, daher würde ich es wahrscheinlich erst einmal mit Fingerangaben versuchen, bei denen der »Stencil« bzw. der Text mit dem Ornamentsymbol überschrieben wurde.

Arnold

harm6

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 :



Code ist auch angehängt.

Gruß,
  Harm


Du darfst diesen Dateianhang nicht ansehen.

harm6

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

Du darfst diesen Dateianhang nicht ansehen.