On 2019-12-19 3:03 pm, Matt Wallis wrote:
What I want to do is to automatically create a click track for any
length of music, and any time signature. For example, if the music is
L measures in length, and the numerator of the time signature is N,
and the denominator is D, then I want a click track that looks like
this:

\repeat unfold <L> \drummode { wbh<D> \repeat unfold <N-1> { wbl\pp }}

I am certain that this can be done using scheme, but I can't figure
out how (I'm a scheme novice).

Here's a quick-and-dirty way to achieve close to what you want:

%%%%
\version "2.19.83"

clickTrack = #(define-music-function (beat meter)
  ((ly:duration? #f) fraction?)
  (let* ((beat (if (ly:duration? beat) beat
                 (make-duration-of-length
                   (ly:make-moment (/ 1 (cdr meter))))))
         (meter-moment (ly:make-moment (/ (car meter) (cdr meter))))
         (beat-moment (ly:duration-length beat))
         (beat-count (floor (ly:moment-main
           (ly:moment-div meter-moment beat-moment))))
         (final-moment (ly:moment-mod meter-moment beat-moment))
         (final-duration (make-duration-of-length final-moment))
         (needs-final? (ly:moment<? (ly:make-moment 0) final-moment)))
    (make-sequential-music
      (map (lambda (n)
        (cond
          ((eqv? 0 n) #{ \drummode { wbh $beat \ff } #})
          ((eqv? beat-count n) #{ \drummode { r $final-duration } #})
          (else #{ \drummode { wbl $beat \pp } #})))
        (iota (if needs-final? (1+ beat-count) beat-count))))))

clickTrackDuring = #(define-music-function (beat meter music)
  ((ly:duration? #f) fraction? ly:music?)
  (let* ((music-length (ly:music-length music))
         (meter-moment (ly:make-moment (/ (car meter) (cdr meter))))
         (repeat-count (floor (ly:moment-main
           (ly:moment-div music-length meter-moment)))))
  (if (ly:duration? beat)
    #{ \repeat unfold $repeat-count \clickTrack $beat $meter #}
    #{ \repeat unfold $repeat-count \clickTrack $meter #})))

melody = \fixed c' {
  \time 4/4
  \repeat unfold 2 { | { e2 g } } \bar "||"
  \repeat unfold 2 { | \tuplet 3/2 { e2 g e } } \bar "||"
  \repeat unfold 2 { | { e4 g b g } } \bar "||"
  \repeat unfold 2 { | \tuplet 5/4 { e4 g b g e } } \bar "||"
  \repeat unfold 2 { | \tuplet 6/8 { e8 g b d' b g } } \bar "||"
}

\score {
  \new Staff { \melody }
  \layout { }
}
\score {
  <<
    \new Staff { \melody }
    \new DrumStaff { \clickTrackDuring 4/4 \melody }
  >>
  \midi { \tempo 4 = 100 }
}
%%%%

Firstly, \clickTrack is a function for generating one measure of clicking based on a desired beat and meter. The beat defaults to the denominator of the meter if unspecified. If the beat duration does not divide the measure perfectly, a final rest is inserted to pad out the measure. Here are examples of use:

%%%%
  \repeat unfold 8 \clickTrack 2  4/4 % click on 1 and 3
  \repeat unfold 8 \clickTrack    4/4 % click on all four
  \repeat unfold 8 \clickTrack 4. 6/8 % click on 1 and 4
  \repeat unfold 8 \clickTrack 4  6/8 % click on 1, 3, and 5
  \repeat unfold 8 \clickTrack    6/8 % click on all six
%%%%

Secondly, \clickTrackDuring is a very basic wrapper for \clickTrack that automatically repeats the click measure to cover the duration of the specified music. Note that no attempt is made to handle music that changes time signature nor music with \partial measures or other funny business. If you had a anacrusis, you would need to manually offset the music:

%%%%
  % Assume \musicWithPickup begins with \partial 4
  \clickTrackDuring 3/4 { s2 \musicWithPickup }
%%%%


-- Aaron Hill

Reply via email to