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
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
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
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
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
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
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
\override
s in the result if an optional argument is given, drop the optional
argument, and make a separate function that does the \override
s.
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 |
|
Music ( |
Event function |
|
Post-event ( |
Scheme function |
|
Any ( |
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
\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
\version "2.25.8"
\markup reddish = \markup \with-color "LightCoral" \etc
\markup \reddish "Hello"
Output
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
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, forSequentialMusic
,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 anelement
, 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 aClusterNoteEvent
:(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
, toPercentRepeatedMusic
.\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
- (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, whilemusic-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
- (map-some-music function music)
Like
for-some-music
, butelements
andarticulations
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
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
andFLAT
are conveniently defined as 1/2 and -1/2, respectively. There are alsoSEMI-SHARP
,SEMI-FLAT
and others, all at the start of the source filescm/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 whileees''
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
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
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.