Autor Thema: Bogen unter Silben im Markup-Text  (Gelesen 4068 mal)

temuta

  • Member
Bogen unter Silben im Markup-Text
« am: Freitag, 10. Mai 2013, 23:52 »
Guten Abend,

ich habe folgendes Problem: Bei Liedern kommt es immer wieder vor, dass in späteren Strophen, die als Markup-Text unter dem Notentext stehen, die Silbenverteilung nicht zu den Noten passt. Mehrere Silben zu einer Noten kann man ja einfach mit dem Befehl \tied-lyric erzeugen. Das Gegenteil, d.h. dass mehrere Noten zu einer Silbe zu singen sind, wird üblicherweise durch einen Bogen unter der Silbe angezeigt. Im folgenden Beispiel

\version "2.16.2"
% Noten und Strophe 1
\relative c'' { c4 d e2 }
\addlyrics { \set stanza = "1." Eins zwei drei }
% Strophen 2-3
\markup {
  \column {
     "2. Vier fünf sechs."
     "3. Vier fünf."
  }
}

sollte in Strophe etwa das einsilbige Wort "Vier" auf die zwei Noten c und d gebunden gesungen werden, während das Wort "Fünf" auf das e gesungen werden soll. Dies möchte ich durch einen Bogen unter dem Wort "Vier" anzeigen lassen. Einen Ausschnitt aus dem Gotteslob (Nr. 108) habe ich als Beispiel angefügt.

Ich habe leider keine Möglichkeit gefunden, mit LilyPond einen solchen Bogen unter einer Silbe eines Wortes zu zeichnen. Habe ich da etwas übersehen? Danke!
Burkard

harm6

  • Member
Re: Bogen unter Silben im Markup-Text
« Antwort #1 am: Samstag, 11. Mai 2013, 11:30 »
Hallo Burkhard,

Zitat von: temuta
Habe ich da etwas übersehen?

wie soll ich's sagen?
Falls Du sonst auf den internationalen Listen wirklich jede mail liest, und Dich auch noch nach Monaten an jede erinnerst, ja, dann hast Du etwas übersehen. ;)

Es gibt nämlich, das sonst nicht weiter beachtete und bislang nicht weiter bearbeitete, geschweige denn implementierte issue 3088

Der Code ist von Jan Nieuwenhuizen.
Ich habe noch zwei weitere properties eingefügt:
  • adjust-length um die Länge besser manipulieren zu können und
  • adjust-x-pos um eine Verschiebung in X-Achse möglich zu machen

Jan's Beispiel-Code ist auskommentiert, Dein Beispiel eingefügt.
Die ganzen FIXME-Kommentare habe ich drin gelassen, sie richten sich an denjenigen der daraus einen patch machen möchte. Für jetzt kannst Du sie also getrost ignorieren.
Die Version aus issue 3088 war 2.14.0. Ich habe sie zwar auf 2.16.2 geändert, der Code funktioniert jedoch nachwievor mit 2.14, 2.16 und auch mit 2.17.17

%%FIXME: add `\undertie "undertied"' to regression/markup-commands.ly

\version "2.16.2"

%% FIXME: c&p from stencil.scm -- define-public and remove copy
#(define (make-bezier-sandwich-stencil coords thick xext yext)
  (let* ((command-list `(moveto
                        ,(car (list-ref coords 3))
                        ,(cdr (list-ref coords 3))
                        curveto
                        ,(car (list-ref coords 0))
                        ,(cdr (list-ref coords 0))
                        ,(car (list-ref coords 1))
                        ,(cdr (list-ref coords 1))
                        ,(car (list-ref coords 2))
                        ,(cdr (list-ref coords 2))
                        curveto
                        ,(car (list-ref coords 4))
                        ,(cdr (list-ref coords 4))
                        ,(car (list-ref coords 5))
                        ,(cdr (list-ref coords 5))
                        ,(car (list-ref coords 6))
                        ,(cdr (list-ref coords 6))
                        closepath)))
  (ly:make-stencil
    `(path ,thick `(,@' ,command-list) 'round 'round #t)
    xext
    yext)))

%% FIXME: rewrite generic wrt axes and replace make-parenthesis-stencil
#(define (make-bow-stencil width height thickness angularity)
 "Create a bow stencil.
 @var{width} is the width of the bow markup.
 @var{thickness} is the thickness of the bow.
 @var{height} is the heigth of the bow.
 The higher the value of number @var{angularity},
 the more angular the shape of the bow."
   (let* ((line-width 0.1)
          (base-x (if (< width 0) (- width) 0))
          (base-y (if (< height 0) (- height) 0))
          (x-extent (ordered-cons 0 width))
          (y-extent (ordered-cons 0 height))
          (left-x (interval-start x-extent))
          (right-x (interval-end x-extent))
          (inner-y 0)
          (outer-y height)
          (left-end-point (cons left-x inner-y))
          (right-end-point (cons right-x inner-y))
          (outer-control-y (+ inner-y (* 4/3 outer-y)))
          (inner-control-y (+ outer-control-y
                             (if (< height 0) thickness (- thickness))))
          ;; keeping angularity allows for refactoring and
          ;; merging with make-parenthesis-stencil
          (offset-index (- (* 0.6 angularity) 0.8))
          (left-control-x (interval-index x-extent offset-index))
          (right-control-x (interval-index x-extent (- offset-index)))
          (left-outer-control-point
             (cons left-control-x outer-control-y))
          (right-outer-control-point
             (cons right-control-x outer-control-y))
          (right-inner-control-point
             (cons right-control-x inner-control-y))
          (left-inner-control-point
             (cons left-control-x inner-control-y)))

   (make-bezier-sandwich-stencil
     (list right-inner-control-point
           left-inner-control-point
           left-end-point
           right-end-point
           left-outer-control-point
           right-outer-control-point
           right-end-point
           left-end-point)
     line-width
     x-extent
     y-extent)))

%% FIXME: replace make-parenthesis-stencil by this:
#(define (make-parenthesis-stencil height width thick angularity)
  (ly:stencil-rotate-absolute
    (make-bow-stencil height width thick angularity)
    -90 0 0))

%% FIXME: c&p from bezier-bow.cc
#(define (F0_1 x) (* (/ 2 PI) (atan (* PI x 0.5))))
#(define (slur-height w h_inf r_0)
   (F0_1 (* (/ (* w r_0) h_inf) h_inf)))

#(define (make-tie-stencil width thickness)
  (let* ((height-limit 1)
         (ratio 0.33)
         (angularity 0.5)
         (height (slur-height width height-limit ratio)))
  (make-bow-stencil width (* -1 height) thickness angularity)))

#(define-markup-command (undertie layout props arg)
  (markup?)
#:category font
#:properties ((thickness 1)
              (offset 2)
              (adjust-length 0)
              (adjust-x-pos 0))
"
@cindex undertie-ing text

Undertie @var{arg}. Looks at @code{thickness} to determine line
thickness, and @code{offset} to determine line y-offset.

@lilypond[verbatim,quote]
\\markup \\line {
\\undertie \"undertied\"
\\override #'(offset . 5)
\\override #'(thickness . 1)
\\undertie \"undertied\"
\\override #'(offset . 1)
\\override #'(thickness . 5)
\\undertie \"undertied\"
}
@end lilypond"
  (let* ((line-thickness (ly:output-def-lookup layout 'line-thickness))
         (thick (* thickness line-thickness))
         (markup (interpret-markup layout props arg))
         (x1 (car (ly:stencil-extent markup X)))
         (x2 (cdr (ly:stencil-extent markup X)))
         (w (- x2 x1 adjust-length (* 2 line-thickness)))
         (y (* line-thickness (- offset)))
         (tie (ly:stencil-translate
                (make-tie-stencil w thick)
                (cons (+ line-thickness adjust-x-pos) y))))
  (ly:stencil-add markup tie)))
 
%{
\markup \line {
  \underline "underlined"
  \undertie "undertied"
  \override #'(offset . 5)
  \override #'(thickness . 1)
  \undertie "undertied"
  \override #'(offset . 1)
  \override #'(thickness . 5)
  \undertie "undertied"
  "Eng" \undertie "ele" "en"
}
%}

% Noten und Strophe 1
\relative c'' { c4 d e2 }
\addlyrics { \set stanza = "1." Eins zwei drei }
% Strophen 2-3
\markup {
  \column {
    \line {
      "2."
      \override #'(adjust-x-pos . 0.5)
      \override #'(adjust-length . 1)
      \undertie Vier
      fünf sechs.
    }
    "3. Vier fünf."
  }
}


HTH,
  Harm

temuta

  • Member
Re: Bogen unter Silben im Markup-Text
« Antwort #2 am: Samstag, 11. Mai 2013, 16:11 »
Hallo Harm,
wow, super - das klappt perfekt. Wenn man das ganze mit einer \concat-Konstruktion einsetzt, kann man bei unveränderten Zusatz-Parametern genau die gewünschten Buchstaben der Silbe mit dem Bogen unterlegen. Für das gescannte Beispiel aus dem Gotteslob-Lied Nr. 108 wäre das dann einfach
\concat { "jetzt und ewig. " \undertie "A" "men." }Wunderbar, das ist ein tolles "Geschenk" zum Wochenende. Danke nochmals und viele Grüße,
Burkard

harm6

  • Member
Re: Bogen unter Silben im Markup-Text
« Antwort #3 am: Samstag, 11. Mai 2013, 17:51 »
Hi Burkard,

freut mich, daß es Dir gefällt.
Der Dank geht an Jan Nieuwenhuizen.
Das einzige worüber ich noch nachdenke ist, ob es sinnvoll sein könnte die Höhe des Bogens variabel, d.h. überschreibbar, zu machen.

Gruß,
  Harm

db5fx

  • Member
Re: Bogen unter Silben im Markup-Text
« Antwort #4 am: Freitag, 31. Mai 2013, 14:19 »
Hallo!
Ich bin begeistert - genau danach habe ich vor etwa zwei Monaten auch gesucht. Bei mir war es jedoch eine andere Nummer aus dem Gotteslob.

Vielen Dank auch für diesen Hinweis!


Bei den Psalmen insbesondere taucht zu dem Bogen auch eine eckige Klammer auf, vergleichbar mit ligature brackets, um mehrere Silben auf einer Note zu singen (siehe Bild).

Ich habe jetzt versucht, den Code von Jan Nieuwenhuizen für solche Klammern anzupassen, bekomme es aber nicht hin. Für die LHP (Lillypond-Hardcore-Programmierung) bin ich wohl noch zu jung ...  ;)

Ich habe diese underbraces mit einem PDF-Editor nachträglich eingefügt, das ist aber auch nicht der Weisheit letzter Schluss. Wie würde man so etwas in Lilypond direkt machen? Vielleicht gibt es das ja auch schon?

Gruß, Andi

Be-3

  • Member
Re: Bogen unter Silben im Markup-Text
« Antwort #5 am: Freitag, 31. Mai 2013, 19:09 »
Hallo Andi,

das Schwierige an der \undertie ist ja, den Bogen aus Bézier-Kurven zusammenzubasteln.
Bei einer einfachen eckigen Klammer ist das alles weit weniger aufwendig.

Ich habe als Vorlage die Definition von \underline kopiert und dort statt eines Strichs die ly:bracket-Funktion eingebaut.

Ähnlich wie bei Harms \undertie-Variante gibt es zusätzlich noch einen Pair-Parameter adjust-x, mit dem man den rechten und linken Rand der Klammer verschieben kann und den Parameter height, mit demsich die Höhe der Klammer ändern läßt.

\version "2.16.2"

% copied from underline
#(define-markup-command (underbracket layout props arg)
  (markup?)
  #:category font
  #:properties ((thickness 1) (offset 2) (height 4) (adjust-x (cons 0 0)))
  "
@cindex underbracketing text

Underbracket @var{arg}.  Looks at @code{thickness} to determine lin thickness,
@code{offset} to determine line y-offset, @code{height} to determine bracket height,
and @code{adjust-x} to adjust left and right borders.

@lilypond[verbatim,quote]
\\markup \\fill-line {
  \\underbracket \"underbracketed\"
  \\override #'(offset . 5)
  \\override #'(height . 3)
  \\override #'(thickness . 2)
  \\override #'(adjust-x . (0.5 . -0.5)
}
@end lilypond"
  (let* ((thick (ly:output-def-lookup layout 'line-thickness))
         (underline-thick (* thickness thick))
         (markup (interpret-markup layout props arg))
         (x1 (+ (car (ly:stencil-extent markup X)) (car adjust-x)))
         (x2 (+ (cdr (ly:stencil-extent markup X)) (cdr adjust-x)))
         (y1 (* thick height))
         (y2 (* -1 thick (+ offset height)))
         (bracket (ly:bracket X (cons x1 x2) underline-thick y1)))
    (ly:stencil-add markup (ly:stencil-translate-axis bracket y2 Y))))



\markup {
  \column {
    \line {
      \underline "Und"
      \override #'(adjust-x . (3.1 . -2.6))
      \underbracket "alle Zeit."
    }
  }
}

Viele Grüße
Torsten

« Letzte Änderung: Freitag, 31. Mai 2013, 19:11 von Be-3 »

db5fx

  • Member
Re: Bogen unter Silben im Markup-Text
« Antwort #6 am: Freitag, 31. Mai 2013, 20:46 »
Hallo Thorsten!

Was soll ich sagen: Ich bin wunschlos glücklich! (bis zum nächsten Problem ...)

Irgendwie mutet(n) diese Programmiersprache(n) schlimmer an als Assembler.  Ich kann zwar geringfügig an den Parametern drehen, aber mit dem Konzept komme ich nicht wirklich klar.


Vielen herzlichen Dank und schönen Abend!

Fröhlichen Gruß, Andi