Music objects#

The first step of LilyPond’s processing is parsing the input into music objects and applying music functions.

Defining music functions#

Music functions are the fundamental tool to create and modify music objects. The template to write one is:

myFunction =
#(define-music-function (arg1 arg2 ...) (type1? type2? ...)
   body...)

This defines a function that can be called as \myFunction. The arguments arg1, arg2, …, must satisfy the type predicates type1?, type2?, …, respectively. The body is a sequence of Scheme expressions; as with any Scheme function, they are evaluated in order and the value of the last expression is returned. Here is a simple music function:

\version "2.25.8"

withNoteNames =
#(define-music-function (music) (ly:music?)
   #{
     <<
       \new Voice $music
       \new NoteNames $music
     >>
   #})

\withNoteNames \relative c' { c d e c e f g e }
Output../../images/b383c7e78c2e4a4d73d51e0b96c8e37a9d35a9c966530ca10ea23cfc43bfe4ff.svg

Argument type checking#

All arguments to a music function are checked for being of the expected type. Because Scheme has only latent typing, where you cannot retrieve the type of an object but only know whether an object belongs to a certain type, type1?, type2?, etc. are type predicates.

\version "2.25.8"

nrepeats =
#(define-music-function (n music) (index? ly:music?)
   #{ \repeat unfold #n { #music } #})

\nrepeats 4 aes
Output../../images/9f13463f918497ed9764545be8a617894c7e37295df7493d36a2e511638c6ed7.svg

The above (somewhat boring) music function is a shortcut for \repeat unfold .... It takes two arguments, called n and music. They must be an integer and a music object, respectively. When the function is called, the checks (index? n) and (ly:music? music) are performed.

This becomes particularly interesting when you consider this example:

\version "2.25.8"

keyDuring =
#(define-music-function (duration pitch) (ly:duration? ly:pitch?)
   #{ \key #pitch \major s $duration \key c \major #})

\new Staff <<
  { c'4 c' c' c' }
  { s2 \keyDuring 4 aes s4 }
>>
Output../../images/9cc50beacfe6b198a54202f312fc51e4f74ec13e08c0667571716640d369c109.svg

We define another function called \keyDuring, with two arguments. It returns a music expression with spacer rests so that the specified key (in major scale) lasts a certain duration, after which C major is used again.

We made the calls:

\nrepeats 4 aes
\keyDuring 4 aes

Even though the arguments are exactly the same, they were obtained with different types. The \nrepeats function got an integer and a music expression. The \keyDuring function, in contrast, got a duration and a pitch! This is thanks to the capabilities of the parser, coupled to the type predicates. When 4 and aes are encountered, different rules are tried, until one is found that allows for a successful match against the type predicate.

Predefined type predicates are listed in the Notation Reference. A table containing the most common ones is found in the Music function primer.

Optional arguments#

An argument is made optional by enclosing its predicate in parentheses. When the function is called without this argument, the value of the parameter is the boolean false. Here is a function that prints a tempo mark with one of the most frequently used values, entered under the form of a term (“Allegro”, “Andante”, etc.). The printed text is optional; the term itself is used when it is not provided.

\version "2.25.8"

tempi =
#'(("Largo" . 50)
   ("Lento" . 60)
   ("Adagio" . 70)
   ("Andante" . 90)
   ("Moderato" . 100)
   ("Allegro" . 140)
   ("Presto" . 170))


commonTempo =
#(define-music-function (printed-term duration term) ((markup?) ly:duration? string?)
   #{
     \tempo $(or printed-term term) $duration = $(assoc-ref tempi term)
   #})


\relative c' {
  \commonTempo 4 Adagio
  c8 d e4 d c
  \commonTempo "Allegro con brio" 4 Allegro
  g'4 e'2 g,4
}
Output../../images/b75b71fed94d841893ade0deafd9517ee84fa962bf8398a22d5c16611874fe83.svg

A default value for an optional parameter may be provided in the parentheses.

\version "2.25.8"

backgroundCluster =
#(define-music-function (grey-level music) ((number? 0.5) ly:music?)
   #{
     <<
       $music
       {
         \once \override ClusterSpanner.layer = 0
         \once \override ClusterSpanner.color = #(rgb-color grey-level grey-level grey-level)
         \makeClusters $music
       }
     >>
   #})

\new Voice \backgroundCluster { <g' b''>2 <c''' g'''> }
\new Voice \backgroundCluster 0.3 { <g' b''>2 <c''' g'''> }
Output../../images/59db711e6b79b769f96bb2d2a22f3a74363750c818d022dd6537b35f7ca2e01a.svg

While optional arguments can be useful at times, they do have limitations.

When the parser expects an optional argument to a music function, it tries the following element against the type predicate expected for this optional argument. If the predicate matches, the value is used for this argument. If it does not match, the argument takes its default value and the value is tried for the next argument. Notably, an important restriction is that a value that did not match the predicate must be used for one of the following argument to the same music function call, but not for something completely unrelated to the music function call afterwards. If this sounds complicated, the thing to remember in practice is that an optional argument is only truly optional if there are mandatory arguments after it, but not if it is the last argument. Let us try to swap the arguments to the \backgroundCluster function above:

\version "2.25.8"

backgroundCluster =
#(define-music-function (music grey-level) (ly:music? (number? 0.5))
   #{
     <<
       $music
       {
         \once \override ClusterSpanner.layer = 0
         \once \override ClusterSpanner.color = #(rgb-color grey-level grey-level grey-level)
         \makeClusters $music
       }
     >>
   #})

\new Voice \backgroundCluster { <g' b''>2 <c''' g'''> } 0.3
% \new Voice \backgroundCluster { <g' b''>2 <c''' g'''> } % Does not work
\new Voice \backgroundCluster { <g' b''>2 <c''' g'''> } \default % Works
Output../../images/b06df4f0e089ae06d77a4d4fe90d8e100e4e9cf6475c69d1ea53a5a8379e58b4.svg

The last line in this example illustrates the way to get around this restriction: the keyword \default can be provided as a placeholder for an optional argument if the parser cannot accept actually omitting it.

Also, keep in mind that arguments are parsed greedily. This can be explained by example, by swapping the duration and term arguments to the commonTempo function shown earlier:

tempi =
#'(("Largo" . 50)
   ("Lento" . 60)
   ("Adagio" . 70)
   ("Andante" . 90)
   ("Moderato" . 100)
   ("Allegro" . 140)
   ("Presto" . 170))


commonTempo =
#(define-music-function (printed-term term duration) ((markup?) string? ly:duration?)
   #{
     \tempo $(or printed-term term) $duration = $(assoc-ref tempi term)
   #})


\relative c' {
  \commonTempo Adagio 4 % Error
  c8 d e4 d c
}

As humans, the code makes us understand that \commonTempo is given two arguments, Adagio and 4, and since the function has three arguments of which one optional, this optional argument should take its default value. However, this is not what happens, and the code above produces an error. The reason is that the parser first tries to see if Adagio is suitable for the first optional argument, of type markup?. It is (being a string, Adagio is also a valid markup), therefore Adagio is interpreted as being the value of this optional argument, and the value 4 that follows it is not a valid value for the term argument of type string?. What this means is that when an optional argument is followed by a mandatory argument, a value for the mandatory argument should not be a valid value for the optional argument.

Finally, a word on multiple optional arguments: when several optional arguments occur in a row, omitting one omits all of them.

All that being said, optional arguments are still very useful, and many of LilyPond’s built-in functions use them (e.g., \relative { ... } or \relative c' { ... }, \time 9/8 or \time 2,2,2,3 9/8). However, it may take some thinking to write your functions in a way that accommodates their restrictions. If you are running into trouble, a good strategy is to split out the function into several functions. For example, instead of injecting \overrides in the result if an optional argument is given, drop the optional argument, and make a separate function that does the \overrides.

Other function types#

A music function must return music. There exist other kinds of functions, each constrained to a specific return type. The advantage is that they can be used in more syntactic contexts, because the parser knows the type of the return value in advance. (TODO: check this)

Function type

Definition macro

Return type

Music function

define-music-function

Music (ly:music?)

Event function

define-event-function

Post-event (ly:event?)

Scheme function

define-scheme-function

Any (scheme?)

Void function

define-void-function

Any; return value is ignored

TODO: example.

The \etc shortcut#

There is special syntax, \etc, to write music functions conveniently. The principle is that \etc can be used as a placeholder for one or several arguments at the very end of a sequence of function applications. This is best understood through example:

\version "2.25.8"

makeClarinetPart = \compressMMRests \transpose bes c' \etc

\makeClarinetPart { c' d' e' }
Output../../images/dad225c4d83f9333ce339565a48c8a7bf1f41a53377566d9a7323573b741d067.svg

\etc also works in a some other contexts:

\version "2.25.8"

padText = \once \override TextScript.padding = \etc

{ \padText 1.8 c'4^"piu mosso" }
Output../../images/2136c03e0c36634d09fa82e217dab9b18622ac6179487a52ef9af204d43d65aa.svg
\version "2.25.8"

\markup reddish = \markup \with-color "LightCoral" \etc

\markup \reddish "Hello"
Output../../images/c5a7258e1473be0169b623edd28f5c5877605c7d669bc515ecd8056de01d0f40.svg

Music expressions#

The examples above were just using the parameters passed to our music functions to build expressions in LilyPond syntax. This is useful for syntactic sugar. However, music functions are much more powerful – just think of \transpose. They allow for analyzing and building music objects.

To understand how some particular music expression is constructed, the most straightforward way is the \displayMusic music function, or, equivalently, the display-scheme-music Scheme function. It attempts to print out a loadable Scheme code that would create an equal music expression. Let us take a first example:

\version "2.25.8"

\displayMusic { c' d'-> }
Output../../images/704978902f15234c5d689dd7c95a47e1c981b2b27a2268c12c9ea79601d66a7d.svg

On the console, this prints:

(make-music
  'SequentialMusic
  'elements
  (list (make-music
          'NoteEvent
          'pitch
          (ly:make-pitch 0 0)
          'duration
          (ly:make-duration 2))
        (make-music
          'NoteEvent
          'articulations
          (list (make-music
                  'ArticulationEvent
                  'midi-extra-velocity
                  20
                  'articulation-type
                  "accent"))
          'duration
          (ly:make-duration 2)
          'pitch
          (ly:make-pitch 0 1))))

Every music object has a type. Possible types are listed in the Internals Reference at Music expressions. Moreover, it holds properties that describe it. NoteEvent objects, for instance, typically have a pitch and a duration (pitch and duration properties). Optionally, they may contain articulations (articulations property). Note that the music type does not prescribe the set of properties; music objects are structured by conventions, not rules. It is allowed to read, define and set arbitrary music properties on arbitrary music objects, although the most common case is defining/setting properties that are understood by LilyPond’s built-in functions and engravers.

In addition, a music type belongs to certain music classes. These are used to group together certain kinds of events that require similar processing. They are listed at Music classes in the Internals.

Music types are written in CamelCase, music classes in lowercase-with-dashes.

(music-is-of-type? music class)

Test if music belongs to the music class class.

Music properties#

Once you have a music object at hand, you can do cool processing by changing its properties. The relevant functions are ly:music-property and ly:music-set-property!. Refer to Probs for details.

Certain music expressions contain other music expressions. This is generally in one of these properties:

  • elements, a list of music objects, for SequentialMusic, SimultaneousMusic and various other kinds of music containers.

  • articulations, also a list, for all post-events attached to a note or rest.

  • element, a single music object, for use by music objects that can only meaningfully contain one other music object. For example, RelativeOctaveMusic has an element, the music that has been converted to relative octave.

The name property of a music object holds its type (like NoteEvent) as a symbol. However, recognition based on event classes should be preferred in most cases.

Constructing music from scratch#

Music objects may also be built directly, allowing for algorithmic composition or simply adding articulations.

(make-music name property1 value1 property2 value2 ...)

Make a music object.

name is the music type, given as symbol. The remaining arguments are paired: every property name (a symbol) is followed by the value of the property.

Properties may be given twice; later values override the former.

You may also pass a music object instead of one property-value pair. In this case, properties are taken from this object. Remaining property-values can override them. For example, here is how you might turn a NoteEvent into a ClusterNoteEvent:

(make-music 'ClusterNoteEvent
            some-note-event)

Music transformation tools#

Music objects are deeply nested structures. Often you cannot know the nesting in advance. For example, note events may be located at any depth in SequentialMusic, RelativeOctaveMusic, SimultaneousMusic, etc.

The tools described here allow for recursively processing music.

(music-map function music)

Create a new music object by applying function deep-first. That is, function is first applied to the bottom music objects, those that do not contain any other music object. These are replaced in their containing music expressions, and the function is applied again, until the top expression is reached.

For the sake of efficiency, music-map acts destructively on its music input. This means that in some cases, Copying music is required.

Here is an example making parts with all repeats changed to percent repeats. This is a matter of converting all types of repeats, characterized by the music class repeated-music, to PercentRepeatedMusic.

\version "2.25.8"

percentRepeats =
#(define-music-function (music) (ly:music?)
   (music-map
     (lambda (m)
       (if (music-is-of-type? m 'repeated-music)
           (make-music 'PercentRepeatedMusic
                       m)
           m))
     music))

notes =
\relative {
  \clef bass
  \repeat unfold 2 <<
    { s4 <g a c ees> s <gis b d f> s <a c ees g> s <gis b d f> }
    \\
    { c, s g s c s g s }
  >>
}

{ \notes }
\percentRepeats \notes
Output../../images/b2e94acb8737efafda8fafa97a936a61b1afaac0b4382514c0f6940f8a9f0303.svg
(music-filter predicate music)

Remove all music expressions in music that do not satisfy predicate.

(for-some-music function music)

This is similar to music-map, but the function is applied on the top music expression, then on its children, etc. Also, for-some-music does not return the result. The function should mutate its argument. This is useful for setting music properties, while music-map is of more use when constructing new music objects.

The music is recursed into only if function returns false. Thus, function can be thought of as “Should we stop?”, except that it is also meant to change the music.

A simple example is a function to add a certain articulation on all notes. This takes advantage of the stop condition to avoid adding articulations on all notes in a chord, which would lead to duplicate marks.

\version "2.25.8"

addStaccato =
#(define-music-function (music) (ly:music?)
   (for-some-music
     (lambda (m)
       (if (or (music-is-of-type? m 'note-event)
               (music-is-of-type? m 'event-chord))
           (begin
             (ly:music-set-property!
               m
               'articulations
               (cons
                 (make-music 'ArticulationEvent 'articulation-type 'staccato)
                 (ly:music-property m 'articulations)))
             #t)
           #f))
     music)
   music)


\addStaccato { c' d' <e' f'> }
Output../../images/f7e1a0cabdf0c7f5fc1f48148f992dc3bde58770399a76bb66ffcdae30638e4d.svg
(map-some-music function music)

Like for-some-music, but elements and articulations resulting from applying function that are not music are ignored, allowing for filtering.

Copying music#

Because music-map and friends can mutate their input, it is sometimes needed to copy music objects.

(ly:music-deep-copy music)

Recursively make a deep copy of music.

Pitches#

Pitches are the bread-and-butter of note entry. The are found in every NoteEvent and KeyChangeEvent. It is not uncommon for music functions to act on them.

The most common method for inputting a pitch is writing using the chosen input note names given by \language. This also works with variables and inside #{ ... #}.

\version "2.25.8"

myPitch = ces
\transpose c \myPitch { c' e' g' c'' }

$(let ((my-other-pitch #{ bes, #}))
  #{ \transpose c #my-other-pitch { c' e' g' c'' } #})
Output../../images/8b0d7e81d18df2dee45de6d0a9ad4ab98bea501cd7090904141dc40d117b9e14.svg

You can also construct pitches programmatically from Scheme using ly:make-pitch shown below.

LilyPond defines pitches as having three components: the octave, the note name, and the alteration. Importantly, a pitch is not a mere frequency: C sharp and D flat are different pitches.

A number of functions are exported to deal with pitches. All are documented in the Internals page listing Scheme functions. Here are the most important ones.

(ly:make-pitch octave note alteration)

Construct a pitch object.

octave is an integer. Zero is the octave containing middle C.

note is an index on the scale, from 0 (C) to 6 (B).

alteration (optional argument) is a fraction: 0 means natural, 1/2, sharp, and -1/2, flat. Arbitrary values may be passed, allowing for double or microtonal alterations.

The global constants SHARP and FLAT are conveniently defined as 1/2 and -1/2, respectively. There are also SEMI-SHARP, SEMI-FLAT and others, all at the start of the source file scm/lily-library.scm.

(ly:pitch-octave pitch)
(ly:pitch-notename pitch)
(ly:pitch-alteration pitch)

Functions to extract the components from pitch.

(ly:pitch-steps pitch)

The number of steps from middle C to pitch. This takes into account the octave and note name, but not the alteration. For instance, dis'' is 8 steps above middle C while ees'' is 9 steps above.

(ly:pitch-tones pitch)

The number of tones from middle C as a rational number. This adds up contributions from octave, note and alteration.

(ly:pitch-transpose pitch delta)
(+ pitch delta)

Transpose pitch by delta. Using \transpose c' #delta applies this operation to each pitch in the music.

The result is uniquely defined by two properties:

  • (ly:pitch-steps result) is the sum of (ly:pitch-steps pitch) and (ly:pitch-steps delta),

  • (ly:pitch-tones result) is the sum of (ly:pitch-tones pitch) and (ly:pitch-tones delta).

The fact that the tone numbers are added means that the transposition is correct aurally. That the step numbers are also added means that the transposition is additionally correct enharmonically (e.g., adding delta = A sharp transposes by an augmented sixth, while adding delta = B flat transposes by a minor seventh).

The form with + is new in version 2.25.7.

(ly:pitch-diff pitch root)
(- pitch root)

Return the pitch delta such that root transposed by delta equals pitch.

\transpose #p1 #p2 ... turns each pitch from the music into (ly:pitch-transpose pitch (ly:pitch-diff p2 p1)).

The form with - is new in version 2.25.7.

Durations and moments#

Every note has a duration, which defines how it is printed. It is typically entered after the pitch of the note. Thus, 8 or 4..*3/8 are durations. More precisely, a duration is defined by a main length indicator, a dot count and an optional multiplier factor. The main length corresponds to 8 or 4 in the previous examples. It is represented by a negative base-2 log: 0 means whole note, 1 is a half note, 2 is a quarter note, etc. The multiplier, a rational number, is the *3/8 part of 4..*3/8. When it is given, it scales the length of the duration without changing the way in which the note is printed. The length matters for synchronization between different voices, for horizontal spacing, and for MIDI rendition. Observe how lengths are modified in this snippet:

\version "2.25.8"

<< { c''4 4*1/2 4*1/2 4..*4/7 4 } \\ { c'4 4 4 4 } >>
Output../../images/f408ed92284d8bc8fea5f0cc7130bd1d64023a7b328c018fbbc3ece1a0e32072.svg

A moment is a length or point in time, as notes have in MIDI. It can be roughly thought of as a fraction. However, grace notes pose a particular challenge in that they would have zero length if moments were only expressed on this scale. Therefore, a moment actually consists of two rationals, a main part and a grace part.

You can obtain the length of a duration as a moment. The reverse conversion is not possible, simply because several different durations can have the same length. A moment lasting 7/8 of an eighth note is the length of the duration 16.., but also the length of 8*7/8. In the output, the first is reflected by a double-dotted sixteenth note while the second is an eighth note (perhaps part of a Baroque score where complex tuplets are written without too much care for exact values).

Durations are commonly entered using the familiar LilyPond syntax. This also works inside #{ ... #}; try:

\version "2.25.8"

myDuration = ##{ 4.. #}
{ c' $myDuration }
Output../../images/89aa7a2ab7bc6779e397db03367115ab0176155daf7371bf2449894989f9a1a5.svg

Durations can also be constructed via a Scheme interface. On the other hand, moments are not typically entered by users and only constructed via Scheme.

(ly:make-duration length dot-count factor)

Make a duration object.

(ly:duration-length duration)

The length of duration as a moment.

(ly:duration-log duration)
(ly:duration-dot-count duration)
(ly:duration-scale duration)

Extract either component of a duration.

(ly:make-moment main-part grace-part)

Make a moment object, with main-part and grace-part given as rational numbers.

(ly:music-length music)

Return the total length of music, as a moment.

(ly:moment-main moment)
(ly:moment-grace moment)

Extract the main or grace part of moment.

(ly:moment-add moment1 moment2)
(+ moment1 moment2)
(ly:moment-sub moment1 moment2)
(- moment1 moment2)
(ly:moment-mul moment rational)
(* moment rational)
(ly:moment-div moment rational)
(/ moment rational)
(ly:moment-mod moment rational)

Arithmetic on moments.

Addition and subtraction simply add and subtract the main and grace parts, respectively. Multiplication and division work between a moment and a rational number (meaning a Scheme fraction like 5/6; integers are a special case of fractions). If you understand and like this formulation, moments are simply the isomorphically unique 2-dimensional vector space over ℚ.

The forms with standard Scheme operators (+, -, * and /) are new in version 2.25.7.