Skip to content

Music Functions 2: Start Doing something Useful

In the previous post I demonstrated how to include Scheme code in LilyPond input files, and we saw our first music function, although it still was a static function only producing a hard-coded middle c. Today we'll do some more by writing functions that actually do something useful and can handle arguments.

Recall: Another static function

[Please note: I use “static function” in the colloquial sense and not in the sense of object oriented programming.]

makeRedNote =
#(define-music-function (parser location)()
   #{
     \once \override NoteHead.color = #red
     \once \override Stem.color = #red
   #})

\relative c' {
  c4 \makeRedNote c c c
}

second-music-function

As in the example of the previous post this music function returns a hard-coded music expression, only that it doesn't return actual music but rather two overrides that will color the next note red. If you'd want to cover arbitrary music you'd have to override other grobs too, e.g. Flag, Beam, Dots etc.

Making the Function More Flexible: Arguments

Of course it would be dull to copy the function for all colors we might want to apply. A better approach is to parametrize the function by accepting an argument for the color. In the last post we already saw how arguments can be added to the function definition:

colorNote =
#(define-music-function (parser location my-color)
   (color?)
   #{
     \once \override NoteHead.color = #my-color
     \once \override Stem.color = #my-color
   #})
 ```

I added `my-color` to the list of arguments and provided the `color?` predicate as the single element in the list of argument types. (By convention one writes this type list on its own line. Only when it's empty it's often written at the end of the first line because the empty parens on a single line looks somewhat strange. )

This now means that the function expects to be called with an argument of type `color?`. Inside Scheme code this argument can simply be referenced as `my-color`, but in our LilyPond section enclosed by `#{ ... #}` we have once more to change mode back to Scheme by using the `#` in `#my-color` to reference the Scheme variable.

So our function still does produce the two property overrides, but it doesn't use the hardcoded `red` anymore but will apply the color provided when *calling* the function.

```lilypond
\relative c' {
  c4 \colorNote #blue c \colorNote #'(0.5 0.5 0) c c
}

third-music-function

Please have a look at how we call the function now. The function expects an argument of the Scheme type color? which is defined by LilyPond. As you will recall we tell LilyPond to switch to Scheme mode with the # character, so we can pass the Scheme value blue to the function. Alternatively we can create an arbitrary color on-the-fly by passing a list of three values (representing Red, Green, Blue) and pass this as a Scheme value. Finding out how exactly to write Scheme values in LilyPond can be confusing for beginners. Sometimes you write them literally (as with the colors), sometimes you have to prepend a ' or enclose it in '(). Getting used to this issue is one major part of getting used to Scheme in LilyPond, and I can't help you too much with that. Basically everything is explained or at least documented in the Scheme Tutorial of LilyPond's documentation - maybe after having read up to this point you may want to (re-)read that now.

Making It Even More Flexible: Processing a Music Argument

As a next step we can actually pass a music expression to the function. This is done with the type predicate ly:music? (functions and predicates with the ly: prefix are not pure Scheme but defined by LilyPond).

noOp =
#(define-music-function (parser location my-music)
   (ly:music?)
   #{
     #my-music
   #})

This music function takes a music expression as its argument and returns exactly this music expression, so actually it doesn't do anything. But there's one interesting thing I can demonstrate with this. The ly:music? argument is a Scheme music expression, and what we want to return is exactly that. Therefore we don't need to switch to LilyPond mode in the function body and then reference the Scheme variable from there. Instead we can simply write music as the expression inside the function body:

noOpTwo =
#(define-music-function (parser location my-music)
   (ly:music?)
   my-music)

This will return the “result of the evaluation of music” - which is exactly the same as in the previous example, and you can see that calling \noOp or \noOpTwo doesn't make a difference:

\relative c' {
  c4 \noOp c \noOpTwo c c
}

fourth-music-function

Please note: As the second argument - the ly:music we provided the simple c here, as a single note is already a music expression for LilyPond. But often you will want to pass compound music expressions as we'll see in the next example.

Coloring Arbitrary Music with Arbitrary Colors

As a conclusion for today's post we'll write a function that colors an arbitrary music expression with an arbitrary color. For this it will take two arguments, the color and the music. First we will override the color property of a number of grobs with the given color, then we produce the music given as the argument and finally we'll revert the color property of the grobs. Please note the use of \temporary, a rather new feature that isn't available in stable versions before LilyPond 2.18. This will ensure that reverting the property will not revert to the default value (i.e. the color black) but rather to the value that was effective immediately before. If you have to use LilyPond 2.16 you can simply leave that out.

colorMusic =
#(define-music-function (parser location my-color my-music)
   (color? ly:music?)
   #{
     \temporary \override NoteHead.color = $my-color
     \temporary \override Stem.color = $my-color
     \temporary \override Flag.color = $my-color
     \temporary \override Beam.color = $my-color
     \temporary \override Rest.color = $my-color
     \temporary \override Slur.color = $my-color
     \temporary \override PhrasingSlur.color = $my-color
     \temporary \override Tie.color = $my-color
     \temporary \override Script.color = $my-color
     \temporary \override Dots.color = $my-color

     $my-music

     \revert NoteHead.color
     \revert Stem.color
     \revert Flag.color
     \revert Beam.color
     \revert Rest.color
     \revert Slur.color
     \revert PhrasingSlur.color
     \revert Tie.color
     \revert Script.color
     \revert Dots.color
   #})

To test the function I write some more complex music in a variable and call the function in different ways.

myMusic = \relative c' {
  c4. d8 e16 d r cis( d4) ~ | d1 \fermata
}

\relative c' {
  \colorMusic #blue \myMusic
  \colorMusic #red { c4 c } d \colorMusic #green e\f
  \colorMusic #magenta \myMusic

[caption id="attachment_2544" align="aligncenter" width="625"](Click to enlarge) (Click to enlarge)[/caption]

You can see that the function works regardless of getting the music as a single note, a compound expression with curly braces or by passing it the \music variable. But you'll also notice that the accidentals and the dynamic letters aren't colored. But of course there's an easy fix: just add the respective overrides to the function.

Everything's fine now. But looking at the last function definition it seems there's a lot of redundancy here, and redundancy is something we usually want to get rid of. Probably it would be a good idea to factor all this out into a separate function - and that's what we'll do in the next post.

{% credits %}{% endcredits %}


Last update: November 3, 2022