lilypond-user
[Top][All Lists]
Advanced

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

Re: test spanner with controlled gradient / dynamic volume curve indicat


From: Michael Winter
Subject: Re: test spanner with controlled gradient / dynamic volume curve indicated by grey level
Date: Tue, 30 Jan 2018 17:00:22 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2

That is really beautiful. Thank you. I have been giving myself a crash course in scheme and was also getting somewhat closer to a solution using a glissando event. Then the internet went down. And low and behold it woke up to your response.

So this is almost what I want. And I need to dissect your code a bit more (again, still wrapping my head around scheme). Maybe I can adapt it. My ultimate goal is to specify the gradient within the given note length (as opposed to giving a new color directive for every note. This is where it gets tricky. In my current attempt (drowning in the deep end), it is a bit tricky because you cannot change colors in the middle of a path directive. So you need to combine several markups (as in my original example). I was piecing together stuff I found on LSR and in the user archive and was also having a huge problem with alignment. My current code is pasted below. It is a mess, but getting there. I just was reading about returning markup definitions in hopes that I could iterate through the gradient and build the markup that way.

En fin, I will study your code. Like I said, it is almost exactly what I want except I want the gradient within the note length. Of course, any help in that direction will be much appreciated.

Best,

Michael


#(set-global-staff-size 16)

\layout {
  indent = 0.0\cm
  \context {
      \Staff
      % \override NoteHead.transparent =##t
      \override StaffSymbol.line-count = #1
      \override Glissando.minimum-length = #0
      \override Glissando #'bound-details = #'((right (attach-dir . 0) (end-on-accidental . #f) (padding . 0.)) (left (attach-dir . 0) (padding . 0.)))

      \remove "Clef_engraver"
      \remove "Time_signature_engraver"
       \stemDown
    }
    \context {
      \Voice
      \consists "Horizontal_bracket_engraver"
    }
}

glissWidth = #1 %<< global variable for glissando width

#(define (path-gliss handle)
  (lambda (grob)
    (if (ly:stencil? (ly:line-spanner::print grob))
    (let* ((stencil (ly:line-spanner::print grob))
          (X-ext (ly:stencil-extent stencil X))
          (Y-ext (ly:stencil-extent stencil Y))
          (width (interval-length X-ext))
          (height (interval-length Y-ext))
          (lefty (cdr (assoc 'Y (ly:grob-property grob 'left-bound-info))))
          (righty (cdr (assoc 'Y (ly:grob-property grob 'right-bound-info))))
          (deltay (- righty lefty))
          (dir (if (> deltay 0) 1 -1)))

      (ly:stencil-translate
        (grob-interpret-markup grob
          (markup
            ;(#: tiny (format "~a" (ly:grob-properties grob)))
                ;(format "~a" (cdr (assoc 'Y (ly:grob-property grob 'left-bound-info))))
                ;(#: tiny (format "~a" handle))
        (#:combine
         (#:override
               (cons (quote line-cap-style) (quote square))
         (#:path glissWidth
          (list (list 'moveto 0 -5)
            (list 'lineto (* (- width 1.1) 0.5) -5))))

         (#:override
               (cons (quote line-cap-style) (quote square))
               (#:with-color
          (list 0.5 0.5 0.5)
          (#:path glissWidth
          (list (list 'moveto (* (- width 0.1) 0.5) -5)
            (list 'lineto (- (* width 1) 1.1) -5)))))
         (#:override
               (cons (quote line-cap-style) (quote square))
               (#:with-color
          (list 0.8 0.5 0.5)
          (#:path glissWidth
          (list (list 'moveto 0 1)
            (list 'lineto (* width 0.5) 1)))))

         )))
        (if (> dir 0)
           (cons (interval-start X-ext) (+ (interval-start Y-ext) 0.1))
           (cons (interval-start X-ext) (+ (interval-start Y-ext) height)))))
     #f)))


#(define (add-gliss m)
   (case (ly:music-property m 'name)
     ((NoteEvent) (set! (ly:music-property m 'articulations)
                      (append (ly:music-property m 'articulations)
                         (list (make-music (quote GlissandoEvent)))))
                   m)
     (else #f)))

addGliss = #(define-music-function (parser location music)
                 (ly:music?)
           (map-some-music add-gliss music))



\new Score
  \with {
    %proportionalNotationDuration = #(ly:make-moment 1/16)
    %\override SpacingSpanner.strict-note-spacing = ##t
    %\override SpacingSpanner.uniform-stretching = ##t
  }
  <<

  \new Staff
  <<
   \repeat unfold 32 { \repeat unfold 63 { s16 \noBreak } s16 \break }
    {\time 4/4 \override Glissando.breakable = ##t
  \override Glissando.after-line-breaking = ##t
  \addGliss {

                 \override Glissando #'stencil = #(path-gliss '(0 0))
                 b'16 b'16 b'8 b'4 \override Staff.Beam.color = #(x11-color 'grey60) b'8 b'16 b'16 ~ \once \override NoteColumn.glissando-skip = ##t b'16 b'16 b'8
    }}
  >>

  >>


On 01/30/2018 03:32 PM, Thomas Morley wrote:
2018-01-30 6:19 GMT+01:00 Michael Winter <address@hidden>:
A bit more here. I think I can fake this in a markup... See example pasted
below. My scheme skilz are minimal. I would like yo do this interpolating
between the x position of adjacent notes. So maybe I can do this as a custom
beam stencil. or some kind of spanner. Basically I want a scheme function
that will give me the position of a given note and the next note... Thanks!

\relative c'' {
   s64
   -\markup {
     \combine
     \override #'(line-join-style . miter)
     \with-color #(x11-color 'grey60)
     \path #2
     #'((moveto 0 0)
      (lineto 0.3 0)
      (closepath)
      )

    \combine
     \override #'(line-join-style . miter)
     \with-color #(x11-color 'grey40)
     \path #2
     #'((moveto 0.3 0)
      (lineto 0.6 0)
      (closepath))

     \override #'(line-join-style . miter)
     \with-color #(x11-color 'grey20)
     \path #2
     #'((moveto 0.6 0)
      (lineto 0.9 0)
      (closepath))

   }


}


On 01/29/2018 06:27 PM, Michael Winter wrote:
Hello...

I have tried quite a few hacks, but nothing really suitable.

What I really want is to simple draw a line beneath the staff that has a
grey scale gradient such that for each note, I give a target value.

Most of what I have tried involves doing this in increments with
overlapping spanners, I also tried the code in this thread:
https://lists.nongnu.org/archive/html/lilypond-user/2016-10/msg00097.html

I think the answer is doing this with svg directives since in the svg
documentation there are directives for linear gradients, but I do not know
how to build the function to use svg directives and such that the target
greyscale value is reached at the x-position of a given notehead.

Also, ideally I would be able to use spacer rests to give intermediary
values along the way, since the curve is actually not linear.

Thanks in advance and my apologies if I have been unclear.

Best,
Michael


Hi Michael,

not sure I've got you right.

Probably the quick hack below may give you a starting point.
It will not work with spacers though, because they don't cause a NoteColumn.

Cheers,
   Harm

#(define (make-filled-box-stencil-list x-coords half-thick colors rl)
   (if (null? (cdr x-coords))
       rl
       (make-filled-box-stencil-list
         (cdr x-coords)
         half-thick
         (cdr colors)
         (cons
           (stencil-with-color
             (make-filled-box-stencil
               (cons (car x-coords) (cadr x-coords))
               (cons (- half-thick) half-thick))
             (car colors))
           rl))))

\version "2.19.65"

foo =
\override TextSpanner.stencil =
   #(lambda (grob)
     (let* ((ncs (ly:grob-object grob 'note-columns))
            (nc-ls
              (if (ly:grob-array? ncs)
                  (ly:grob-array->list ncs)
                  '()))
            (sys (ly:grob-system grob))
            (nc-exts
              (map
                (lambda (nc)
                  (ly:grob-extent nc sys X))
                nc-ls))
            (left-info
              (ly:grob-property grob 'left-bound-info))
            (right-info
              (ly:grob-property grob 'right-bound-info))
            (thick (ly:grob-property grob 'thickness 1))
            (x-coords
              (map
                (lambda (e)
                  (- e (assoc-get 'X left-info)))
                `(
                  ,(assoc-get 'X left-info)
                  ,@(map
                    interval-center
                    (drop-right (drop nc-exts 1) 1))
                  ,(assoc-get 'X right-info))))
           (ls (iota (1- (length x-coords)) 20 20))
           (color-gradient
             (assoc-get 'color-gradient (ly:grob-property grob 'details) '(1)))
           ;; overkill below ...
           (safe-color-gradient-ls
             (append
               color-gradient
               (make-list (length x-coords) (last color-gradient))))
           (color
             (assoc-get 'color (ly:grob-property grob 'details)))
           (colors
             (map
               (lambda (n)
                 (x11-color (string->symbol (format #f "~a~a" (or color
'grey) n))))
               safe-color-gradient-ls)))
     (apply
       ly:stencil-add
       (make-filled-box-stencil-list x-coords thick colors '()))))

{
     \override TextSpanner.thickness = 0.5
     %% make sure color and it's gradient exists, otherwise all's black
     \override TextSpanner.details.color = #'grey
     \override TextSpanner.details.color-gradient = #'(60 40 20)
     \foo
     c''2\startTextSpan
     d''
     e''
     f''\stopTextSpan
}

{
     \override TextSpanner.thickness = 0.5
     \override TextSpanner.details.color = #'LightCyan
     \override TextSpanner.details.color-gradient = #'(2 3 4)
     \foo
     c''2\startTextSpan
     d''
     e''
     f''\stopTextSpan
}





reply via email to

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