tabr
Author: Matthew Leonawicz License: MIT
Overview
The tabr
package provides a music notation syntax and a collection of
music programming functions for generating, manipulating, organizing and
analyzing musical information in R. The music notation framework
facilitates creating and analyzing music data in notation form.
Music programming in the notation syntax provided by tabr
can be used
for a variety of purposes, but it also integrates cohesively with the
package’s transcription functions. The package also provides API wrapper
functions for transcribing music notation in R into guitar tablature
(“tabs”) using LilyPond.
LilyPond is an open source music engraving program for generating high
quality sheet music based on markup syntax. tabr
generates LilyPond
files from R code and can pass them to LilyPond to be rendered into
sheet music pdf files from R. While LilyPond caters to sheet music in
general and tabr
can be used to create basic sheet music, the
transcription functions focus on leveraging LilyPond specifically for
creating quality guitar tablature.
While LilyPond is listed as a system requirement for tabr
, you can use
many package functions without installing LilyPond if you do not intend
to render tabs.
Use case considerations
tabr
offers a useful but limited LilyPond API and is not intended to
access all LilyPond functionality from R, nor is transcription via the
API the entire scope of tabr
. If you are only creating sheet music on
a case by case basis, write your own LilyPond files manually. There is
no need to use tabr
or limit yourself to its existing LilyPond API or
it’s guitar tablature focus.
However, if you are generating music notation programmatically, tabr
provides the ability to do so in R and offers the added benefit of
converting what you write in R code to the LilyPond file format to be
rendered as printable sheet music.
With ongoing development, the music programming side of tabr
will
likely continue to grow much more than the transcription functionality.
Why LilyPond for transcription?
LilyPond is an exceptional sheet music engraving program.
- It produces professional, high quality output.
- It is open source.
- It offers a command line access point for a programmatic approach to music notation.
- It is developed and utilized by a large community.
- Most GUI-based applications are WYSIWYG and force a greater
limitation on what you can do and what it will look like after you
do it. It is only for the better that
tabr
is the bottleneck in transcription limitations rather than the music engraving software it wraps around.
Functionality and support
The tabr
package offers the following:
- Render guitar tablature and sheet music to pdf or png.
- Write accompanying MIDI files that can respect repeat notation and transposition in the sheet music (under reasonable conditions).
- Support tablature for other string instruments besides guitar such as bass or banjo.
- Support for instruments with different numbers of strings.
- Support for arbitrary instrument tuning.
- Offers inclusion (or exclusion) of formal music staves above tab staves, such as treble and bass clef staves for complete rhythm and timing information.
- If music staff is included, the tab staff can be suppressed, e.g., for vocal tracks.
- Track-specific setup for features like instrument type, tuning and supplemental music staves.
- Provides common notation such as slide, bend, hammer on, pull off, slur, tie, staccato, dotted notes, visible and silent rests.
- Allows arbitrary tuplet structure.
- Above-staff text annotation.
- Percent and volta repeat section notation.
- Note transposition.
- Staff transposition.
- Multiple voices per track and multiple tracks per score.
- Chord symbols above staff
- Chord fretboard diagrams and chord chart at top of score.
- A variety of layout control options covering settings from score attributions to font size.
- Optional alternative input format allowing the user to provide string/fret combinations (along with key signature and instrument tuning) to map to pitch.
Installation
You can install tabr from CRAN with:
install.packages("tabr")
You can install tabr from GitHub with:
# install.packages("remotes")
remotes::install_github("leonawicz/tabr")
Noteworthy strings
As a quick introduction and to get oriented to the music notation syntax
offered by tabr
, consider the concept of a noteworthy string. This is
like any other character string, except that what makes a string
noteworthy is that its content consists strictly of valid tabr
music
notation syntax. It can be parsed unambiguously and meaningfully into a
musical phrase (see next section) and can be processed as input to the
various package functions that inspect and manipulate musical
information.
A simple character string like "c e g"
, or alternatively as a vector,
c("c", "e", "g")
, is a noteworthy string. Even "a"
is noteworthy. So
are "a#"
and "a_"
(sharp and flat). However, "A"
is not, nor is
"Z"
. There are other pieces of valid syntax than just the lowercase
letters a
through g
and sharp and flat notation. See the package
vignettes for details.
Noteworthiness can be checked on any character string. No supplemental
class is required. When defining noteworthy strings you can define them
like any other character vector. However, you will notice that package
functions that operate on noteworthy strings and whose output is another
noteworthy string will yield a string with the supplemental noteworthy
class. This has its own print and summary methods. If you remove the
class with a common R operation like as.character()
, it does not
impact any subsequent musical manipulation beyond the need to reperform
a noteworthy check.
x <- "g#4 c5 d#5 g#4c5d#5"
as_noteworthy(x)
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: g#4 c5 d#5 <g#4c5d#5>
is_note(x)
#> [1] TRUE TRUE TRUE FALSE
is_chord(x)
#> [1] FALSE FALSE FALSE TRUE
chord_is_major(x)
#> [1] NA NA NA TRUE
(x <- transpose(x, 1))
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: a4 c#5 e5 <a4c#5e5>
summary(x)
#> <Noteworthy string>
#> Timesteps: 4 (3 notes, 1 chord)
#> Octaves: integer
#> Accidentals: sharp
#> Format: space-delimited time
#> Values: a4 c#5 e5 <a4c#5e5>
distinct_pitches(x)
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: a4 c#5 e5
distinct_pitches(x) %>% pitch_freq() # in Hz
#> [1] 440.0000 554.3653 659.2551
tabr
offers many functions for manipulating musical structures defined
in music notation. See the vignettes for more information on music
programming.
Basic transcription example
Rendering sheet music is based on building up pieces of musical information culminating in a score. The fundamental object to consider in the transcription context is a phrase. A phrase is created from a noteworthy string and incorporates additional information, most importantly time and rhythm. It can also include positional information such as the instrument string on which a note is played. Outside of rendering tabs, there is no reason to construct phrase objects. Everything from the phrase object on up is about using the R to LilyPond pipeline to render some kind of sheet music document.
If you doing music analysis on noteworthy strings and are combining the note, pitch or chord information with time, that can be done with a corresponding variable; using a phrase object is not the way to do that because phrase objects are intended for the construction of LilyPond markup syntax.
As a brief example, recreate the tablature shown in the image above (minus the R logo). Here are the steps.
- Define a musical phrase with
phrase
or the shorthand aliasp
. - Add the phrase to a
track
. - Add the track to a
score
. - Render the score to pdf with
tab
.
The code is shown below, but first some context.
Constructing a musical phrase
A phrase here does not require a strict definition. Think of it as the
smallest piece of musical structure you intend to string together. The
first argument to phrase
is a string describing notes of a specific
pitch (or rests: “r”), separated in time by spaces. For chords, just
remove spaces to indicate simultaneous notes. Integers are appended to
indicate the octave number so that the pitch is unambiguous. For
example, a rest followed by a sequence of notes might be given by notes
= "r a2 c3 f3 d3 a3 f3"
.
The second argument is a similar string giving note metadata. In this
example there is nothing to add but the time durations. Whole notes
taking up an entire measure of music are given by 1, half notes by 2,
quarter notes 4, eighth notes 8, and so on. To specify a quarter note
rest followed by a sequence of eighth notes, use info =
"4 8 8 8 8 8 8"
(or shorten to just info = "4 8*6"
). This basic
example does not require specifying additional note information such as
dotted notes for different fractions of time, staccato notes,
ties/slurs, slides, bends, hammer ons and pull offs, etc. These
specifications are currently available in tabr
to varying degrees of
development and are covered in the vignette tutorials.
The third argument, string
, is optional but generally important for
guitar tablature. In similar format, it specifies the strings of the
guitar on which notes are played. Providing this information fixes the
fret-string combinations so that LilyPond does not have to guess what
position on the neck of the guitar to play a specific note. An inability
to specify this in various tablature notation software (or laziness by
the user), is a common cause of inaccurate tabs scouring the internet,
where even when the notes are correct they are written in the tab
suggesting they be played in positions no one would sensibly use. Note
that the x
shown below is just a placeholder indicating no need to
specify a string for the quarter note rest.
The example below employs a couple shortcuts to further reduce typing.
The first is to use the *
in-string expansion operator mentioned above
to avoid typing a long series of eighth notes. Second, it drops explicit
reference to octave number three since this central octave is the
default octave in LilyPond. This applies to all but the first note
below.
While explicit string numbers are not needed for this example, they are
provided anyway for full context. Dropping the string
argument would
further reduce typing.
Score metadata and accessing LilyPond
Finally, specify some song metadata to reproduce the original staff: the key of D minor, common time, and the tempo.
If LilyPond is installed on your system (and added to your system path
variable on Windows systems), tab
should call it successfully. Windows
users are recommended to just add LilyPond’s bin
directory to the
system path. This will take care of LilyPond as well as its bundled
Python and MIDI support. As an example for Windows users, if the
LilyPond executable is at C:/Program Files
(x86)/LilyPond/usr/bin/lilypond.exe
, then add C:/Program Files
(x86)/LilyPond/usr/bin
to the system path.
R code
library(tabr)
p("r a2 c f d a f", "4 8*6", "x 5 5 4 4 3 4") %>% track %>% score %>%
tab("phrase.pdf", key = "dm", time = "4/4", tempo = "4 = 120")
#> #### Engraving score to phrase.pdf ####
#> GNU LilyPond 2.18.2
#> Processing `./phrase.ly'
#> Parsing...
#> Interpreting music...
#> Preprocessing graphical objects...
#> Interpreting music...
#> MIDI output to `./phrase.mid'...
#> Finding the ideal number of pages...
#> Fitting music on 1 page...
#> Drawing systems...
#> Layout output to `./phrase.ps'...
#> Converting to `./phrase.pdf'...
#> Success: compilation successfully completed
For comparison, if you were using string-fret specification to construct the above phrase, one way to do so is the following:
sfp("r;r;4 5;0;8 3 4;3; 0 3;2; 4;3;")
#> <Musical phrase>
#> r4 <a,\5>8 <c\5>8 <f\4>8 <d\4>8 <a\3>8 <f\4>8
It may not look particularly beneficial here, but for more complex music
it can be easier to reason about the phrase under construction when
using this format to bind information by time step rather. See
?sf_phrase
for a comparison with phrase
and the various ways you can
do phrase construction in tabr
for equivalent results. If you are
looking to do quick, easy and basic tabbing, you may want to consider
using the single-argument input method of the sf_phrase
function. The
package vignettes focus on general use cases using the phrase
function
rather than sf_phrase
.
Note above that tabr
also exports the pipe %>%
operator. Even given
the hierarchy of objects involved in the series of steps to move from a
phrase to a rendered pdf, a short example like this does not even
require a single assignment. While music can be quite complex and a full
score will be much longer, tabr
strives to minimize the work while
still forcing some sense of interpretable, organized structure. For long
and complex music, it can require some effort and practice to ensure
your approach to transcription in your R code is not opaque.
References and resources
There are several vignette tutorials and examples at the tabr
website.
R-Music
R for music data extraction and analysis
See the R-Music organization on GitHub for more R packages related to music data extraction and analysis. The R-Music blog provides package introductions and examples.
Other packages
- The tuneR package for analysis of music and speech by Uwe Ligges, Sebastian Krey, Olaf Mersmann, and Sarah Schnackenberg.
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.