Compose and play music in R with the Rmusic package

A couple of years ago at Christmas time, I composed a virtuoso version of Jingle Bells to play in my R session, with the help of this old Stackoverflow post. I just went back to this code and turned it into an R package which will play any tune you want to compose.

Installing the package

To install the package, run:

devtools::install_github("keithmcnulty/Rmusic", build_vignettes = TRUE)

Composing music

To compose simple music you’ll need to create two vectors, one of which contains the notes and the other contains the durations of the notes in beats. Both these vectors should be the same length of course.

The notes vector should be a vector of character strings, based on the following rules:

  • Notes go from "A" to "G"
  • Semitones are notated by adding a #(sharp) or b(flat) to the string, eg "A#" or "Bb"
  • The default octave is the 4th piano octave. For lower or higher octaves append the octave number to the string, eg "Ab3", "C3", "G#5"

The duration vector contains simple strings of numerical values representing how many beats for each note, eg 2 or 1.25

Example: Virtuoso Jingle Bells

I like to write the notes vector as strings for each bar of music, and then use strsplit() to break them up into the desired format:

jbells_pitch <- paste(
"E E E",
"E E E",
"E G C D",
"E",
"F F F F",
"F E E E",
"E D D E",
"D G",
"E E E",
"E E E",
"E G C D",
"E",
"F F F F",
"F E E E E",
"G G F D",
"C",
"G3 E D C",
"G3",
"G3 G3 G3 E D C",
"A3",
"A3 F E D",
"B3",
"G G F D",
"E",
"G3 E D C",
"G3",
"G3 E D C",
"A3 A3",
"A3 F E D",
"G G G G A G F D",
"C C5 B A G F G",
"E E E G C D",
"E E E G C D",
"E F G A C E D F",
"E C D E F G A G",
"F F F F F F",
"F E E E E E",
"E D D D D E",
"D D E F G F E D",
"E E E G C D",
"E E E G C D",
"E F G A C E D F",
"E C D E F G A G",
"F F F F F F",
"F E E E E E",
"G C5 B A G F E D",
"C C E G C5"
)
jbells_pitch <- strsplit(jbells_pitch, " ")[[1]]

For the duration vector:

jbells_duration <- c(
1, 1, 2,
1, 1, 2,
1, 1, 1.5, 0.5,
4,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
2, 2,
1, 1, 2,
1, 1, 2,
1, 1, 1.5, 0.5,
4,
1, 1, 1, 1,
1, 1, 1, 0.5, 0.5,
1, 1, 1, 1,
4,
1, 1, 1, 1,
3, .5, .5,
1, 1, 1, 1,
4,
1, 1, 1, 1,
4,
1, 1, 1, 1,
4,
1, 1, 1, 1,
4,
1, 1, 1, 1,
3, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
1, 1, 0.5, 0.5, 0.5, 0.5,
1, 1, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
1, 0.5, 0.5, 1, 0.5, 0.5,
1, 0.5, 0.5, 1, 0.5, 0.5,
1, 0.5, 0.5, 0.5, 0.5, 1,
1, 0.33, 0.33, 0.33, 1, 0.33, 0.33, 0.33,
1, 1, 0.5, 0.5, 0.5, 0.5,
1, 1, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
1, 0.5, 0.5, 1, 0.5, 0.5,
1, 0.5, 0.5, 1, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
1, 0.33, 0.33, 0.33, 2
)

You’ll find some other example tunes in the vignettes of the package.

Playing or saving the music

To play the Jingle Bells music in your R session simply run:

Rmusic::play_music(jbells_pitch, jbells_duration)

The play_music() function expects the notes and duration vectors as its first two arguments and also has a tempo argument which has a default value of 240 beats per minute.

To save it as a .wav file simply run:

Rmusic::save_music(jbells_pitch, jbells_duration, output_file = "jbells.wav")

The save_music() function also expects a path to the output .wav file. See the help documentation if needed.

Originally published on towardsdatascience.com on December 16, 2019

Leave a Reply

%d bloggers like this: