For the Scheme gurus.

 

For a long time I have needed to decorate or embellish pedal brackets to
customise them. Two things I need are arrows on the right hand side, and
text markers similar to cautionary pedal indications on the left hand side,
so each new broken bracket shows “1/2 ped” at the start, for example. I am
aware that there have been discussions of similar things on the list, but it
seems the only solutions were workarounds using text spanners. I have found
this to be unsatisfactory, for my purposes. So I have developed Scheme code
to achieve this effect. I am pleased to say I nearly have it working, but I
am bedevilled by the fact that in this example the second line does not get
decorated. I confess I am stumped. I wonder if anyone here can see what must
be some silly error in the logic? I am not saying this is a bug. I am sure
it is my dullness at work.

 

I apologise for this being a fairly complex bit of code to digest, but I
have a feeling many people want this type of pedal customisation judging
from the archived discussions, and I feel it may end up being a useful
contribution, hence worth debugging.

 

One aspect that has me puzzled is that if you add more treble notes so that
two staves are alive for longer the problem shifts around. I would have
thought that pedal on the bottom staff would not be affected by a staff
above, and this behaviour may be a clue to the issue, but I am unable to
hear what it is telling me.

 

My thinking on this to date is that I remain very ignorant of when things
are laid out and what order, if any, various internal constructions are
done, so I am think this may be to do with the possibility that treating the
broken spanner as an ordered list that is there ready to be modified may be
a fundamental error. For what it’s  worth, therefore, I tried implementing
this as an after line breaking callback, but the same problem shows.

 

Any help most appreciated.

 

Andrew

 

== snip

 

\version "2.19.50"

 

#(use-modules (srfi srfi-1))

 

#(define (make-arrow-path arrow-length arrowhead-height arrowhead-width)

   "Arrow with triangular arrowhead."

   (list

    'moveto 0 0

    'lineto arrow-length 0

    'lineto arrow-length (/ arrowhead-width 2)

    'lineto (+ arrow-length arrowhead-height) 0

    'lineto arrow-length (- (/ arrowhead-width 2))

    'lineto arrow-length 0

    'closepath

    ))

 

pedalWithArrowsAndText =

\once \override Score.PianoPedalBracket.stencil =

#(lambda (grob)

 

   ;; function to modify the individual grob part

   (define add-decorations

     (lambda (g list-length)

       (let* (

               ;; unpack the argument

               (index (car g))

               (grobber (cadr g))

               (last (= index list-length))

 

               ;; Get the default-stencil and its x-dimension and x-length.

               (stil (ly:piano-pedal-bracket::print grobber))

               (stil-x-extent (ly:stencil-extent stil X))

               (stil-x-length (interval-length stil-x-extent))

 

 

               ;; make arrow for the rhs end

               (thickness 0.1)

               (arrowhead-height 1.0)

               (arrowhead-width 1.0)

               (arrow-length 1.0)

               (arrow (make-path-stencil (make-arrow-path arrow-length
arrowhead-height arrowhead-width) thickness 1 1 #t))

               (new-stil (if (not last)

                             (ly:stencil-combine-at-edge stil X RIGHT arrow
-0.105)

                             stil))

 

 

               ;; make text for the lhs end

               (text-stil

                (grob-interpret-markup grobber

                  (markup

                  #:line

                   (#:abs-fontsize

                    6

                    (#:sans

                     (#:upright

                      (#:whiteout (#:box (#:pad-markup 0.3 "½ ped")))))))))

 

               (new-stil (ly:stencil-stack new-stil X LEFT text-stil -6)))

 

         (ly:grob-set-property! grobber 'stencil new-stil))))

 

   (let* (

           (stil (ly:piano-pedal-bracket::print grob))

           (orig (ly:grob-original grob))

           (pieces (if (ly:grob? orig)

                       (ly:spanner-broken-into orig)

                       '()))

           (pieces-indexed-list (zip (iota (length pieces) 1) pieces))

           (pieces-length (length pieces)))

 

     ;; We want arrows on all segments but the last, and text on all
segments, so

     ;; we have to pass some notion of list index to the function doing the

     ;; decorating. Hence the ziplist combining grob segment and index in
pairs.

 

     (let loop ((x 1)

                (count 0))

       (if (< count 5)

           (begin

            (add-decorations (list-ref pieces-indexed-list count)
pieces-length)

            (loop x (+ count 1))

            )))

 

     stil))

 

%===========================================================================
================

 

treble = {

  \clef treble

  \time 4/4

  c'4 c' c' c'

  c' c' c' c'

}

 

bass = {

  \clef bass

  \time 4/4

 

  c4

  \pedalWithArrowsAndText

  c\sustainOn c c

  c c c c

  \break

  c c c c

  \break

  c c c c

  \break

  c c c c

  \break

  c c c c\sustainOff

 

}

 

\score {

 

  \new PianoStaff

  <<

    \new Staff = "treble"  { \treble }

    \new Staff = "bass" { \bass }

  >>

 

  \layout {

    \context {

      \Score

      pedalSustainStyle = #'bracket

    }

  }

}

 

== snip

 

 

_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to