lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A slur across a line break with change of clef in another staff gene


From: Lucas Werkmeister
Subject: Re: A slur across a line break with change of clef in another staff generates bad output
Date: Sun, 4 Mar 2018 22:53:12 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0

Hi,

On 04.03.2018 13:54, Thomas Morley wrote:
Hi Lucas,

2018-03-04 0:03 GMT+01:00 Lucas Werkmeister <address@hidden>:
Hi everyone,

I stumbled across a bug where Lilypond generates a bad slur if the slur
crosses a line break and there is a simultaneous clef change in a different
staff. I found a previous report for this bug in the mailing list archives
(2015-05-30, same subject), but with Google Code being archived and
SourceForge currently in Disaster Recovery mode, I’m not sure if the bug is
currently tracked anywhere (or even fixed in the development version), so I
thought I could still post my tiny(ish) example along with a workaround, and
perhaps it would be helpful to someone :)
It's
https://sourceforge.net/p/testlilyissues/issues/3287/
not fixed yet

Example (you can replace the 7 with other numbers), with workaround
commented out:

\version "2.18.2"
<<
  \new Staff {
    s1*7 |
    % \temporary \alterBroken control-points #'(((0.3 . 1.5) (1.3 . 2.3)
(2.5 . 2.3) (3.5 . 1.5)) ((3.3 . 1.5) (4.3 . 2.3) (5.5 . 2.3) (6.5 . 1.5)))
Slur
    r2.. d''8( | \break
    % \revert Slur control-points
    c'')
  }
  \new Staff {
    \clef "violin"
    s1*7 s1 \clef "bass"
  }
The control points aren’t perfect,
since I couldn’t figure out how to get the automatically chosen control
points (for the second half of the broken slur, we could just reuse these,
since only the first half is bad, and the first half could be based on them
as well), so I had to try to match them by eyeballing.
For this purpose the shape-command was developed, thanks David Nalesnik.
I wasn’t sure if it would be possible to use \shape in this case, since I needed to not just tweak but pretty much replace the control points of the first part, and I thought it would be more difficult to figure out the correct offsets to an unknown starting set of control points. On the other hand, being able to specify an empty list of adjustments for the second part and therefore keeping the original control points is a benefit I hadn’t considered.
Though, you may try to set minimum-length instead, directly or via \alterBroken.
In my eyes it looks already nice then.

All three possibilities demonstrated below (comment in/out to test):

\version "2.18.2"

<<
  \new Staff {
    s1*7 |
    r2..

    %% (1) the \shape command
    \shape
      #'(
         ;; change cps of first part
         ((1.8 . 0)(1.8 . 0.8)(1 . 0.8)(1 . 0))
         ;; don't change cps of second part, thus provide an empty list
         ()
         )
      Slur

    %% (2) override 'minimum-length
    %\once \override Slur.minimum-length = 6

    %% (3) \alterBroken with 'minimum-length
    %\alterBroken minimum-length #'(6 0) Slur
    d''8( | \break
    c'')
  }
  \new Staff {
    \clef "violin"
    s1*7 s1 \clef "bass"
  }

Thank you very much, I really like the minimum-length tweak :) the slur stops before the clef in the lower staff instead of going across it (might be another effect of the same bug), but I can live with that.

Also, this
unfortunately doesn’t work if you want double slurs, since AFAIK it’s not
possible to set the control points in that case. But still, it’s better
than nothing IMHO.
For shaping double-slurs the following may help (I used some extreme
values for the show-effect):

In my case the minimum-length solution works for the double slur as well, so I’ll just stick to that.

\version "2.18.2"

%% c/p from shape-function in music-functions-init.ly
#(define (shape-curve offsets grob coords)
  (let* ((orig (ly:grob-original grob))
         (siblings (if (ly:spanner? grob)
                       (ly:spanner-broken-into orig) '()))
         (total-found (length siblings)))
    (define (offset-control-points offsets)
      (if (null? offsets)
          coords
          (map coord-translate coords offsets)))

    (define (helper sibs offs)
      (if (pair? offs)
          (if (eq? (car sibs) grob)
              (offset-control-points (car offs))
              (helper (cdr sibs) (cdr offs)))
          coords))

    ;; we work with lists of lists
    (if (or (null? offsets)
            (not (list? (car offsets))))
        (set! offsets (list offsets)))

    (if (>= total-found 2)
        (helper siblings offsets)
        (offset-control-points (car offsets)))))

#(define (shape-double-slurs offsets)
  (lambda (grob)
    (let* ((dir (ly:grob-property grob 'direction)))
      (ly:grob-set-property! grob 'control-points '())
      (ly:grob-set-property! grob 'after-line-breaking
        (lambda (grob)
          (let ((cps (ly:slur::calc-control-points grob)))
            (ly:grob-set-property! grob 'control-points
              (if (> dir 0)
                  (shape-curve (car offsets) grob cps)
                  (shape-curve (cdr offsets) grob cps)))))))))

shapeDoubleSlurs =
#(define-music-function (parser location offsets)(pair?)
#{
  \once \override Slur.before-line-breaking = #(shape-double-slurs offsets)
#})


\score {
  \new Staff {
    \set doubleSlurs = ##t
    \shapeDoubleSlurs
      #'(
         ;; upside Slur
         (
           ((0 . 0) (14 . 10)(-14 . 10)(0 . 0))
         )

         . ;; n.b it's a pair

         ;; downside Slur
         (
           ((0 . 0) (0 . -6)(-20 . -6)(0 . 0))
         )
         )
    c'1( c''2 c'')
    \shapeDoubleSlurs
      #'(
         ;; upside Slur
         (
           ;; first part
           ((0 . 0) (-8 . 2)(8 . 2)(-2 . 0))
           ;; second part
           ((6 . 0) (0 . 0)(0 . 0)(-6 . 0))
         )

         . ;; n.b it's a pair

         ;; downside Slur
         (
           ;; first part
           ((0 . 0) (20 . -4)(-20 . -4)(0 . 0))
           ;; second part
           ((0 . 0) (13 . -3)(-10 . -4)(0 . 0))
         )
         )
    c'1( c''2 c''
    \break
    c''2 c'')
  }
  \layout { line-width = 60 }
}


HTH,
  Harm

Thanks again, this was very helpful!

Cheers,
Lucas

reply via email to

[Prev in Thread] Current Thread [Next in Thread]