There are two interpretations of the package name gm:
They correspond to two functionalities of the package:
Let’s start with a quick example.
Let’s go through the code line by line:
music <-
defines a variable.Music()
initializes a Music
object.+ Meter(4, 4)
adds a 4/4 time signature.+ Line(c("C5", "D5", "E5", "F5"))
adds four notes.show(music)
generates the music.We don’t have to stop here. We can add more components. For example, add a tempo:
Add an articulation:
Add a pedal:
There are still many other components we can add. Before we dive in, let’s see how to install and configure gm.
Install gm:
Install MuseScore. MuseScore is open source and free notation software. Internally, gm uses MuseScore to generate music.
You don’t need to configure anything if MuseScore is installed to a default path.
Otherwise, please specify the path to the MuseScore executable file in .Renviron file:
MUSESCORE_PATH=<path to MuseScore>
.For example, the environment variable is like
MUSESCORE_PATH=C:/Program Files/MuseScore 4/bin/MuseScore4.exe
in Windows, andMUSESCORE_PATH=/Applications/MuseScore\ 4.app/Contents/MacOS/mscore
in macOS.At the highest level, gm uses Music
objects to represent
music.
As shown in the Example section, the workflow for creating music is usually like this:
Music
object with
Music()
.+
.show()
.A Music
object is represented as a list of data frames.
Each data frame represents some type of components of the music. To
examine a Music
object’s representation, simply print it.
For example, below is the representation of the Music
object created in the Example section:
music <-
Music() +
Meter(4, 4) +
Line(c("C5", "D5", "E5", "F5"))
music
#> Music
#>
#> $meters
#> # A tibble: 1 × 6
#> bar number unit actual_number actual_unit invisible
#> <int> <int> <int> <int> <int> <lgl>
#> 1 1 4 4 4 4 FALSE
#>
#> $notes
#> # A tibble: 4 × 7
#> line i j pitch midi duration length
#> <int> <int> <int> <chr> <int> <chr> <dbl>
#> 1 1 1 NA C5 72 <NA> 1
#> 2 1 2 NA D5 74 <NA> 1
#> 3 1 3 NA E5 76 <NA> 1
#> 4 1 4 NA F5 77 <NA> 1
#>
#> $lines
#> # A tibble: 1 × 7
#> part staff voice segment bar offset name
#> <int> <int> <int> <int> <int> <dbl> <chr>
#> 1 1 1 1 1 1 0 <NA>
We will explore every type of components as we proceed.
Musical lines are the most basic units of music in gm. You can create
a musical line with Line()
.
You can specify the pitches and durations of a musical line with
arguments pitches
and durations
. For
example:
line <- Line(
pitches = c("C5", "D5", "E5", "F5"),
durations = c(0.5, 1, 1.5, 2)
)
music <- Music() + Meter(5, 4) + line
show(music, "score")
If pitches
and durations
have different
lengths, the shorter one will be recycled. This feature is useful for
repeating a pattern. For example:
line <- Line(
pitches = c("A3", "E4", "C5", "B3", "E4", "G#4"),
durations = c("quarter.", "eighth", "quarter")
)
music <- Music() + Meter(3, 4) + line
show(music)
We will talk more about pitches and durations later.
You can insert a musical line at positions other than the first beat
of the first bar with arguments bar
and
offset
. For example:
line <- Line(c("C5", "D5", "E5"), bar = 2, offset = 1)
music <- Music() + Meter(4, 4) + line
show(music, "score")
The musical line is inserted at the second beat of the second bar.
A more interesting example:
pitches <- c(64, 65, 69, 71, 72, 76)
music <- Music() + Meter(4, 4)
for (i in 0:8) {
music <- music + Line(pitches, offset = 0.5 * i)
}
show(music)
The music contains nine parts, with identical pitches and durations. The difference lies in their insertion positions, creating an interesting echo sound effect.
Music can contain more than one musical line. For example:
line_1 <- Line(c("C5", "D5", "E5", "F5"))
line_2 <- Line(c("E4", "G4"), 2)
line_3 <- Line("C4", 4)
music <- Music() + Meter(4, 4) + line_1 + line_2 + line_3
show(music, "score")
You can assign a name to a musical line with argument
name
. For example:
line_1 <- Line(c("C5", "D5", "E5", "F5"), name = "a")
line_2 <- Line(c("E4", "G4"), 2, name = "b")
line_3 <- Line("C4", 4, name = "c")
music <- Music() + Meter(4, 4) + line_1 + line_2 + line_3
show(music, "score")
By default, a musical line is added to the end. You can change it
with argument to
and after
. For example:
line_1 <- Line(c("C5", "D5", "E5", "F5"), name = "a")
line_2 <- Line(c("E4", "G4"), 2, name = "b")
line_3 <- Line("C4", 4, name = "c", to = "a", after = FALSE)
music <- Music() + Meter(4, 4) + line_1 + line_2 + line_3
show(music, "score")
Now the third musical line is added to the beginning.
There is a hierarchy of musical lines:
From the perspective of a music score,
You can specify the hierarchy with argument as
. For
example, the following music has two parts:
music <-
Music() +
Meter(4, 4) +
Line(c("C5", "D5", "E5", "F5")) +
Line(c("C4", "G4"), 2, as = "part")
show(music, "score")
The following music has one part, and this part has two staffs:
music <-
Music() +
Meter(4, 4) +
Line(c("C5", "D5", "E5", "F5")) +
Line(c("C4", "G4"), 2, as = "staff")
show(music, "score")
The following music has one part of one staff, and this staff has two voices:
music <-
Music() +
Meter(4, 4) +
Line(c("C5", "D5", "E5", "F5")) +
Line(c("C4", "G4"), 2, as = "voice")
show(music, "score")
Actually, the three examples above all sound the same. The hierarchy of musical lines is only discernible from the score.
The following music has one part of one staff of one voice, and this voice has two segments:
music <-
Music() +
Meter(4, 4) +
Line(c("C5", "D5", "E5", "F5")) +
Line(c("C4", "G4"), 2, as = "segment", bar = 2)
show(music, "score")
Segments are used to insert musical lines into other musical lines.
The $lines
data frame of a Music
object
contains the information about all musical lines. For example:
line_1 <- Line(c("C5", "D5", "E5", "F5"), name = "a")
line_2 <- Line(c("E4", "G4"), 2, name = "b", as = "voice")
line_3 <- Line("C4", 2, name = "c", as = "staff", offset = 2)
music <- Music() + Meter(4, 4) + line_1 + line_2 + line_3
show(music, "score")
music$lines
#> # A tibble: 3 × 7
#> part staff voice segment bar offset name
#> <int> <int> <int> <int> <int> <dbl> <chr>
#> 1 1 1 1 1 1 0 a
#> 2 1 1 2 1 1 0 b
#> 3 1 2 1 1 1 2 c
We can see from the data frame that this music has one part, and this part has two staffs. The first staff has two voices. The second staff is inserted at the third beat.
You can use scientific pitch notations to specify pitches. For example:
pitches <- c("C4", "C#4", "D-4", "C##4", "D--4")
music <- Music() + Meter(5, 4) + Line(pitches)
show(music, "score")
A pitch notation consists of
A MIDI note number is a number between 12 and 127. You can also use MIDI note numbers to specify pitches. For example:
See a conversion table of pitch notations and MIDI note numbers.
An advantage of MIDI note numbers is ease of operation. Suppose we have the following four MIDI note numbers: