lilypond-user
[Top][All Lists]
Advanced

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

Re: My previous request is not of importance


From: David Kastrup
Subject: Re: My previous request is not of importance
Date: Wed, 13 Jun 2012 11:31:35 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.1.50 (gnu/linux)

Matthew Probst <address@hidden> writes:

> Seems the snippet properly applies the current "relative" level to the
> snippet.
>
>
> I'm still curious, however, what the best practice for
> walking/recursing down SequentialMusic data structures is.  My desire
> to get into the Scheme side of things stands.

Here is how I would be doing that snippet using the current version of
LilyPond.  The "old" way of going through music is using the music-map
function.  However, you can't keep music-map from recursing if you
already are at the level you find interesting, and it does this
depth-first.

You can see that I spend some separate complexity on meddling with the
relative pitches via callbacks rather than "properly" replacing the
functions.  Of course, this has the drawback that \displayLilyMusic on
the results will output stuff that is "not relative-correct".  It has
the advantage of presumably working with anything (like pitched trills
and other weird things not likely covered by the original code).

After moving most of the complexity of \relative into one
special-purpose function, the rest illustrating how to descend into and
manipulate structures becomes reasonably straightforward.

It may look like overkill to iterate into rhythmic-event/event-chord
when we usually expect "chord" to be one of those anyway, but this has
the advantage of cutting through possible wrapper layers.

#(define (make-relative-wrappers)
  "This creates two connected functions for creating music containing
repeated instances of possibly relative music.  Both are called on a music
expression and return a wrapped form.  The first function is called
on the entire assembled music, the second function is called on each
instance of the repeated music to be inserted in the assembled music.

The result makes sure that every included instance has the same
octave relations, is transparent to the pitch of relative expressions
surrounding it, yet the total effect of the expression on relative pitch
is that of the included expressions (if at least one of them is encountered)."
   (let ((start-pitch #f) (end-pitch #f))
     (values
      (lambda (m)
        (make-music 'UnrelativableMusic
                    'element m
                    'to-relative-callback
                    (lambda (x p)
                      (set! start-pitch p)
                      (set! end-pitch #f)
                      (let ((fallback (ly:make-music-relative!
                                       (ly:music-property x 'element) p)))
                        (set! start-pitch #f)
                        (or end-pitch fallback)))))
      ; start of implicit contexts does not work with UnrelativableMusic,
      ; so we use an explicit context starter here.
      (lambda (m)
        (make-music 'ContextSpeccedMusic
                    'context-type 'Bottom
                    'element m
                    'to-relative-callback
                    (lambda (x p)
                      (set! end-pitch (ly:make-music-relative!
                                       (ly:music-property x 'element)
                                       (or start-pitch p)))
                      p))))))

rhythmTemplate =
#(define-scheme-function (parser location pattern) (ly:music?)
   (define-music-function (parser location chord) (ly:music?)
     (call-with-values make-relative-wrappers
       (lambda (outer-wrap inner-wrap)
         (outer-wrap
          (map-some-music
           (lambda (m)
             (and (music-is-of-type? m 'skip-event)
                  (let ((dur (ly:music-property m 'duration))
                        (art (ly:music-property m 'articulations))
                        (res (ly:music-deep-copy chord)))
                   ;; transfer duration of skip to all elements with duration
                    (for-some-music
                     (lambda (c)
                       (and (ly:duration? (ly:music-property c 'duration))
                            (begin
                              (set! (ly:music-property c 'duration) dur)
                              #t)))
                     res)
                   ;; transfer articulations of skip to all relevant targets
                    (for-some-music
                     (lambda (c)
                       (and (or (music-is-of-type? c 'event-chord)
                                (music-is-of-type? c 'rhythmic-event))
                            (begin
                              (set! (ly:music-property c 'articulations)
                                    (append (ly:music-property c 'articulations)
                                            art))
                              #t)))
                     res)
                    (inner-wrap res))))
           (ly:music-deep-copy pattern)))))))

rhya = \rhythmTemplate {s8.-> s16 s8}
rhyb = \rhythmTemplate {s8[ r16 s16 s8]}
rhyc = \rhythmTemplate {s16 s~ s4}

rhyd = \rhythmTemplate { \times 2/3 { s8 s8 s8 } s4 s4 s8 s8 s4 }
rhye = \rhythmTemplate { \times 2/3 { s8---\pp s8-- s8-- } s4--
                                      s4-- s8-- s8-- s4-- }
rhyf = \rhythmTemplate { \times 2/3 { s4 \times 2/3 { s8 s-> s } s4 } }

\score
{
 \new Staff \relative c'
 {
  \time 6/8
  \rhya c \rhyb c' |
  \rhya <c, e> \rhyb <c f> |
  \rhyc <c e> \rhyc <c d> |
  \time 5/4
  \rhyd c
  \rhyd e
  \rhye <c e g>
  \time 4/4
  \rhyf c \rhyf d
  }
}

-- 
David Kastrup

reply via email to

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