3

I'm working on a song with a repetitive rhythm that changes pitch. As this would normally involve a large amount of repeated typing, so I would like to define a LilyPond function to do this for me.

I'm completely lost on how to change the note duration (I figured out the argument for a pitch, but have yet to figure out how to add the duration in the function body, considering that * seems to register as invalid syntax, and plain numbers are interpreted as part of the variable name). And, I can only get it to return one note at a time.
Repeating the note variable in the function body as shown below does nothing (this is expected, as Scheme seems to implicitly return only the last value in the function)

Is there any way to get a function like this to work?

Alternatively, is there a way to multiply notes in the same way as measure-long rests are multiplied (R1*n)?

My attempts:

Trying to return multiple values (tried without commas first)

pattern_one = #(define-music-function
         (parser location note)
         (ly:music?)
           note, note, note, note, note, note)

Trying to return list:

pattern_one = #(define-music-function
         (parser location note)
         (ly:music?)
           (note, note, note, note, note, note))

Using LilyPond syntax (this worked, but transposed the entire group of notes up one octave per call to note, and still leaves the problem of duration):

pattern_one = #(define-music-function
         (parser location note)
         (ly:music?)
         #{
           #note #note #note #note #note #note #note
         #})

What I want to happen:

Input: d,

Output: d8 d8 d8 d8 d8 d8

or (preferably): d4 d8 d8 d8 d8 d8 d8

2 Answers 2

4

Your last attempt is almost good, you just need to use $note instead of #note. What's the difference? # introduces a Scheme expression directly as a music expression bypassing any change or interpretation. Which in this case means that you have the identical (not just the same) expression 7 times in a row, and if you transpose the expression, this identical expression in it will get transposed 7 times as well. So you want a copy each time, and $note will achieve that.

On another note, you want to add a rhythm here. That means that note cannot be a music expression (which already would have a duration) but only a pitch. So you should replace the ly:music? predicate with ly:pitch? in order to have $note just be a single pitch.

And the final complication is that if you use

\relative {
   \pattern_one c'
}

you don't want to have this turn into

\relative {
    c'8 c'4 c' c' c' c' c' c'
}

since the octaves will go through the roof, because the ' is applied to each consecutive note. You want any modifiers to apply only to the first occurrence. There is a trick macro for that purpose called make-relative. Putting all of this together, you get

pattern_one = #(define-music-function
     (parser location note)
     (ly:pitch?)
     (make-relative (note) note
     #{
       $note 4 $note 8 $note 8 $note 8 $note 8 $note 8 $note 8
     #}))

Now if you are taking a somewhat recent development version of LilyPond, rhythms can stand on their own so you only actually need a single $note and can save yourself the make-relative trouble. Also argument lists are simpler, so you can write

pattern_one = #(define-music-function (note) (ly:pitch?)
     #{
       $note 4 8 8 8 8 8 8
     #})

Given the legibility and conciseness of that expression, the question is whether the music function is even worth writing in the first place. For more complex rhythms, possibly also involving articulations, it might. For this amount of complexity, it seems a bit of overkill. Also the function will require a lot more work to deal with chords while the written-out version will just work fine with them.

5
  • 1
    You can shorten this by using a "one-note chord" and repeating it with q. In fact you might not need to define a function at all: define riff = { q8 q q4 q8 q16 q } and then something like <e>4 \riff <f>4 \riff.
    – user19146
    Commented Nov 10, 2016 at 23:33
  • When I try the second to bottom function with the macro, it exits with return code 1 and says something about wrong number of arguments
    – cat40
    Commented Nov 11, 2016 at 2:26
  • Actually, it says Non-list result for unquote-splicing note in expression ((unquote-splicing #@1+0)).
    – cat40
    Commented Nov 11, 2016 at 2:34
  • Figured it out. Needed parenthesis around the first note after make-relative. Suggested an edit
    – cat40
    Commented Nov 11, 2016 at 2:48
  • If my function takes more than one pitch as arguments, what is the syntax to make-relative all of them? I am trying to write a function for breaking a 3-note chord by some pattern. (make-relative (n) n (make-relative (m) m (make-relative (k) k … ))) seems to give some surprises.
    – Anonymous
    Commented Feb 9, 2021 at 16:02
2

Is this repetitive rhythm played all on one pitch every time? How about \transpose? First define it:

riff = { d4 d8 d d d d d }

then

\transpose d c' \riff

or whatever pitch you want it at.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.