lilypond-user
[Top][All Lists]
Advanced

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

Re: Notes or chords sustained with a pedal


From: Thomas Morley
Subject: Re: Notes or chords sustained with a pedal
Date: Sun, 22 Dec 2019 12:48:14 +0100

Hi Aaron,

Am So., 22. Dez. 2019 um 07:06 Uhr schrieb Aaron Hill
<address@hidden>:
>
> On 2019-12-21 9:15 am, Kieren MacMillan wrote:
> >> Here is my attempt at hacking the BarLine stencil to add overlapping
> >> ties:
> >
> > This is so cool. Is there an easy way to make the function determine
> > the "current" set of LVs (i.e., the LV configuration from the most
> > recent LV-ed chord) and automagically apply it to the subsequent
> > barlines (e.g., with a \temporary, to be \reverted manually)?
>
> Things get trickier if you need to keep track of past events.  But here
> is another approach that uses a Scheme engraver to do the bulk of the
> work:

this is really great stuff.
How about putting it in LSR?
Seems to work with 2.18.2 as well.

After a very quick first glnce over it some remarks:

> %%%%
> \version "2.19.83"
>
> #(begin
>    (set-object-property! 'activeLaissezVibrer 'translation-type? list?)
>    (set-object-property! 'activeLaissezVibrer 'translation-doc
>      "A list of LaissezVibrerTies which should span BarLines.")
>    (set! all-translation-properties
>      (cons 'activeLaissezVibrer all-translation-properties)))
>
> #(define (SpanLaissezVibrer_engraver context)
>    (define (spanLaissezVibrer? grob)
>      (let* ((cause (ly:grob-property grob 'cause))
>             (class (ly:event-property cause 'class '()))
>             (span? (ly:event-property cause 'span #f)))
>        (and (memq 'laissez-vibrer-event class) span?)))
>    (define (past-events tie)
>      (ly:moment<? (car tie) (ly:context-now context)))
>    (define (rescale-control-points cp xex)
>      (let* ((xmin (apply min (map car cp)))
>             (xmax (apply max (map car cp)))
>             (xmid (/ (+ xmin xmax) 2))
>             (xhw (/ (- xmax xmin) 2)))

        (map (lambda (pt) pt <-- this `pt` looks superfluous or am I
overlooking something?
>          (let ((t (/ (- (car pt) xmid) xhw)))
>            (cons (interval-index xex t) (cdr pt)))) cp)))
>    (define ((stencil-proc ties) grob)
>      (let* ((bd (ly:item-break-dir grob))
>             (orig (ly:bar-line::print grob))
>             (xex (ly:stencil-extent orig X))
>             (x (interval-index xex 0))
>             (w (+ 0.8 (/ (interval-length xex) 2)))
>             (tie-xex (cons (- x w) (+ x w))))

Some code-duplication here, iiuc:

>        (ly:stencil-add (ly:bar-line::print grob)
>          (apply ly:stencil-add
>            (map (lambda (tie)
>              (let* ((cp-orig (ly:grob-property tie 'control-points))
>                     (cp-temp (rescale-control-points cp-orig tie-xex))
>                     (sten '()) (xex '()) (yex '()))
>                (ly:grob-set-property! tie 'control-points cp-temp)
>                (set! sten (ly:tie::print tie))
>                (ly:grob-set-property! tie 'control-points cp-orig)
>                (set! xex (ly:stencil-extent sten X))
>                (set! yex (ly:stencil-extent sten Y))
>                (ly:make-stencil (ly:stencil-expr sten)
>                  (cons (car xex) (if (> 0 bd) x (cdr xex))) yex)))
>              (map cdr ties))))))
>    (make-engraver
>      (acknowledgers
>        ((bar-line-interface engraver grob source-engraver)
>          (let ((ties (ly:context-property context
>                        'activeLaissezVibrer '())))
>            (set! ties (filter past-events ties))
>            (if (not (null? ties)) (ly:grob-set-property!
>              grob 'stencil (stencil-proc ties)))))
>        ((semi-tie-interface engraver grob source-engraver)
>          (if (spanLaissezVibrer? grob)
>            (ly:context-set-property! context 'activeLaissezVibrer
>              (cons (cons (ly:context-now context) grob)
>                (ly:context-property context
>                  'activeLaissezVibrer '()))))))))
>
> spanLaissezVibrer = #(make-music 'LaissezVibrerEvent 'span #t)
>
> stopSpanLaissezVibrers = \applyContext #(lambda (context)
>    (ly:context-set-property! (ly:context-find context 'Staff)
>      'activeLaissezVibrer '()))
>
> Upper = {
>    | r2 r8 g'8 b' c''
>    | <g' b' c''>1\spanLaissezVibrer
>    | R1 \stopSpanLaissezVibrers \bar "||"
>    | r8 a' g' e' c'2 \bar "|."
> }
> Lower = {
>    | <a, d>1\spanLaissezVibrer
>    | R1
>    | g8 b <g b>2.^\spanLaissezVibrer
>    | R1 \stopSpanLaissezVibrers
> }
> \score {
>    \new PianoStaff <<
>      \new Staff { \clef "treble" \Upper }
>      \new Staff { \clef "bass" \Lower }
>    >>
>    \layout { \context { \Staff
>      \consists \SpanLaissezVibrer_engraver } }
> }
> %%%%
>
> This is quite different from my previous manual approach, but this has
> advantages of exactly matching the vertical positioning of LV ties
> without needing manual intervention.
>
>
> -- Aaron Hill

Thanks,
  Harm



reply via email to

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