einfache music-function für Hammer-ons

Begonnen von eichhofener, Montag, 4. März 2019, 12:40

« vorheriges - nächstes »

eichhofener

Liebe Forumsleser!

Ich verwende Lilypond zur Erstellung von Tabs fürs Banjo.
Dort kommen sehr viele Hammer-on (und Pull-offs und slides) vor.

Die Notation die ich bisher verwende ist z.B.
g8(^" H" a)

und das funktioniert auch hinreichend gut (auch wenn das H über dem Bogen nicht immer schön zentriert ist, aber egal.)

weil sowas wirklich oft vorkommt, hätte ich gerne dafür eine einfache music-function z.B. "ho", die ich dann folgendermaßen verwenden möchte.
\ho g8 a

(Das ist sicher nicht die riesige Ersparnis, ich sehe es aber für mich als ersten Schritt in die Lilypond-Programmierung an).

ich habe folgende Definition einer music-function versucht, die aber nicht funktioniert:
#(define-music-function
  (parser location note1 note2)
  (ly:music? ly:music?)
  #{
   $note1 (^" H" $note1 )
  #})

interessanterweise funktionieren aber die Funktionen unten (die die Aufgabe natürlich nicht lösen):
#(define-music-function
  (parser location note1 note2)
  (ly:music? ly:music?)
  #{
   g8 (^" H" a )
  #})

... als auch ...

#(define-music-function
  (parser location note1 note2)
  (ly:music? ly:music?)
  #{
   $note1 $note2
  #})

Ich habe also grundlegende Startschwierigkeiten mit dem Variablenkonzept in Lilypond oder der Scheme-Programmierung allgemein :-)
(habe nur solide C++ / Java-Kenntnisse)
Kann mir hier jemand einen Tipp geben?
Vielen Dank!

~Uwe

Malte

Hallo Uwe,

willkommen im Forum! Bitte gib bei Fragen immer deine verwendete LilyPond-Version an und verwende Code-Tags (siehe hier). Tatsächlich spielt in diesem Fall die Version eine Rolle:\version "2.18.2"

ho =
#(define-music-function
  (parser location note1 note2)
  (ly:music? ly:music?)
  #{
    <>(^"  H" $note1 <>) $note2
  #})

\relative {
  \ho g'8 a \ho g a
}
LilyPond weiß nicht, daß sich hinter ly:music? nur eine einzelne Note versteckt und beschwert sich deshalb, daß es keine Events (Bögen und -"Text") erwartet. Ich habe sie deshalb an zwei leere EventChords <> gehängt. Die haben eine Dauer 0 und tatsächlich hängt sich der Bogen dann korrekt an die Note an, egal, wo sie steht.

\version "2.19.82"

ho =
#(define-music-function
  (note1 note2)
  (ly:music? ly:music?)
  #{
    <>(^"  H" $note1 <>) $note2
  #})

\relative {
  \ho g'8 a \ho g a
}
In Version 2.19.82 ist die Sache immer noch so, allerdings braucht man da die Argumente ,,parser location" für define-music-function nicht mehr.

\version "2.21.0"

ho =
#(define-music-function
  (note1 note2)
  (ly:music? ly:music?)
  #{
    $note1 (^"  H" $note2 )
  #})

\relative {
  \ho g'8 a \ho g a
}
Hier wirds spannend: Seit 2.19.82 ist die Entwicklung weitergegangen und mit den nächsten veröffentlichten Versionen kannst du dann tatsächlich das machen, was du ursprünglich vorhattest, ohne <> als Hilfskonstruktion verwenden zu müssen.

Nur leider ist wegen Fehlern im Buildsystem anscheinend aktuell nicht klar, wann die nächsten Versionen veröffentlicht werden, du müßtest also
• doch die Variante mit <> verwenden
• 2.21.0 selbst kompilieren
• oder, kleiner Überfall: wir haben Glück und du hast zufälligerweise Lust und Zeit, rauszukriegen, was mit dem Build-System schiefläuft ;) Auch sonst sind programmierende Helfer immer gern gesehen ...

Viele Grüße
Malte

eichhofener

vielen Dank für Deine Mühe. Da hast Du mir sehr geholfen.
Ob ich beim build-System helfen kann... mal sehen  :).
(vielleicht wenn ich etwas tiefer in der Materie eingetaucht bin.)

Malte

Was mir grad noch einfällt: Du verwendest ja $, um note1 und note2 aufzurufen. Stattdessen ginge auch #, zu den Unterschieden (und der Empfehlung, wenn beides geht, # zu nutzen) siehe ,,LilyPond Scheme-Syntax" im Extending-Manual.

eichhofener

Hi.

Ich habe ein bißchen weitergemacht. Ich möchte, dass der Text ("H" für Hammer-on bzw. "Po" für Pull-off usw) auf den Slurs stets zentriert erscheint.
Ich habe dazu den Slur-Stencil geändert. Die Textdarstellung klappt auch ganz gut, aber der Slur braucht jetzt natürlich vertikal mehr Platz und die Kollisionserkennung scheitert.

Wie kann ich den geänderten Platzbedarf berücksichtigen? Ich glaube, ich muss die Skylines anpassen, aber wie?
Vielleicht hat jemand einen Fingerzeug.

Vielen Dank und beste Grüße!
Uwe

Anbei ein Beispiel. Ich hoffe es ist einigermaßen "minimal genug".


\version "2.19.82"

bowText =
#(define-music-function (text) (markup?)
#{
  \once \override Voice.Slur.stencil =
    #(lambda(grob)
     ( let*
       (
         (stc-old (ly:slur::print grob))
         (left-x (car (ly:stencil-extent stc-old 0)))
         (stc-text (grob-interpret-markup grob text))
         (stc-new-center (ly:stencil-combine-at-edge
                          (ly:stencil-aligned-to stc-old 0 0)
                          1 1
                          (ly:stencil-aligned-to stc-text 0 0)
                          .3))
         (stc-new-left (ly:stencil-aligned-to stc-new-center 0 -1))
       )
       
       (ly:stencil-translate-axis stc-new-left left-x 0)
     )
   )
#}
)

{
  \repeat volta 2  { c''1 }
  \alternative
  {
    % modified stencil does not leave space. "H" interferes with marker lines of alternative
    {c''4 \bowText H f''( g'') f''}
   
    % version with annotion leaves space (comment out above and comment in below)
    % {c''4  f''(^" H" g'') f''} % text annotation does
  }
}

harm6

Versuch mal
\once \override Slur.vertical-skylines = #grob::always-vertical-skylines-from-stencil
einzufügen.
Das hat wahrscheinlich Nachteile, sonst wärs ja der default. Du mußt halt testen, obs akzeptabel ist.

Gruß,
  Harm

eichhofener

Vielen Dank!
Funktioniert einwandfrei.
Vielleicht ist es nicht default, weil es evtl. nicht so performant ist.
Bei meinen kurzen Banjo Tabs (1-2 Seiten) ist das aber völlig egal.
Ich beginne mich mit Scheme anzufreunden  ;D

Liebe Grüße
Uwe