SkillAgentSearch skills...

Tabr

R package: tabr. Notation-based and tidy music data analysis and transcription.

Install / Use

/learn @leonawicz/Tabr

README

<!-- README.md is generated from README.Rmd. Please edit that file -->

tabr <img src="man/figures/logo.png" align="right" alt="" width="120" />

<!-- badges: start -->

Project Status: Active – The project has reached a stable, usable
state and is being actively
developed. R-CMD-check Codecov test
coverage CRAN
status CRAN
downloads Github
Stars

<!-- badges: end --> <img src="man/figures/README-banner-1.png" width="85%" id="tabr-readme-banner" />

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; i.e, more from the perspective and in the language of a musician than, say, an audio engineer.

Citation

Matthew Leonawicz (2026). tabr: Music Notation Syntax, Manipulation, Analysis and Transcription in R. R package version 0.5.5. https://CRAN.R-project.org/package=tabr

Contribute

Contributions are welcome. Contribute through GitHub via pull request. Please create an issue first if it is regarding any substantive feature add or change.

Installation

Install the CRAN release of tabr with

install.packages("tabr")

Install the development version from GitHub with

# install.packages("remotes")
remotes::install_github("leonawicz/tabr")

Motivating example

as_music("r8 c d e f g a b c'1") |> plot_music_guitar()
<img src="man/figures/README-plot_music-1.png" width="50%" style="display: block; margin: auto;" />

Music data structures

It’s easiest to begin with a high level view using some basic examples.

Music data can be viewed, manipulated and analyzed while in different forms of representation based around different data structures: strings and data frames. Each representation offers advantages over the other for different use cases.

Music syntax can be entered directly and represented in character strings to minimize the formatting overhead of data entry by using simple data structures, for example when wanting to quickly enter and transcribe short pieces of music syntax in R into sheet music or tablature files. You can also enter sound and time together with the music class, and no need to repeat consecutive durations until a change.

Here is an example of making a string of pitches noteworthy and a string of combined pitch and duration into a music object. Such objects carry various musical information based on the syntax of an input string.

library(tabr)

x <- "a, c e g# a ac'e' ac'e'~ ac'e' a c' e' a'"
x <- as_noteworthy(x)
x
#> <Noteworthy string>
#>   Format: space-delimited time
#>   Values: a, c e g# a <ac'e'> <ac'e'~> <ac'e'> a c' e' a'

summary(x)
#> <Noteworthy string>
#>   Timesteps: 12 (9 notes, 3 chords)
#>   Octaves: tick
#>   Accidentals: sharp
#>   Format: space-delimited time
#>   Values: a, c e g# a <ac'e'> <ac'e'~> <ac'e'> a c' e' a'

y <- "a,8 c et8 g# a ac'e'4. ac'e'~8 ac'e'4 at4 c' e' a'1"
y <- as_music(y)
summary(y)
#> <Music string>
#>   Timesteps: 12 (9 notes, 3 chords)
#>   Octaves: tick
#>   Accidentals: sharp
#>   Key signature: c
#>   Time signature: 4/4
#>   Tempo: 2 = 60
#>   Lyrics: NA
#>   Format: space-delimited time
#>   Values: a,8 c8 et8 g#t8 at8 <ac'e'>4. <ac'e'~>8 <ac'e'>4 at4 c't4 e't4 a'1

music_split(y)
#> $notes
#> <Noteworthy string>
#>   Format: space-delimited time
#>   Values: a, c e g# a <ac'e'> <ac'e'~> <ac'e'> a c' e' a'
#> 
#> $info
#> <Note info string>
#>   Format: space-delimited time
#>   Values: 8 8 t8 t8 t8 4. 8 4 t4 t4 t4 1
#> 
#> $lyrics
#> [1] NA
#> 
#> $key
#> [1] "c"
#> 
#> $time
#> [1] "4/4"
#> 
#> $tempo
#> [1] "2 = 60"

Functions exist for directly performing various mathematical, logical and organizational operations and musical transformations on strings like the one above by checking their music syntax validity and adding custom classes and methods to these strings (more on this below). tabr offers special object classes that facilitate working with music data and notation in ways that are natural to R, robust, tidy, and lend themselves well to transcription as well as analysis.

Of course, none of this will work on character strings that are not “noteworthy” or “musical”, for example. Invalid, unworthy syntax is rejected early with an error, preventing corrupted music syntax from causing unexpected issues later on.

The same music data can also be organized in tidy data frames, allowing for a more familiar and powerful approach to the analysis of large amounts of structured music data.

x <- "a,8 c e r r c a, g#, a ac'e'"
as_music(x) |> as_music_df()
#> # A tibble: 10 × 14
#>    duration pitch note  semitone octave  freq pitch_int scale_int slur  slide
#>    <chr>    <chr> <chr>    <int>  <int> <dbl>     <int> <chr>     <chr> <lgl>
#>  1 8        a,    a           57      2  110.        NA <NA>      <NA>  FALSE
#>  2 8        c     c           48      3  131.         3 m3        <NA>  FALSE
#>  3 8        e     e           52      3  165.         4 M3        <NA>  FALSE
#>  4 8        r     r           NA     NA   NA         NA <NA>      <NA>  FALSE
#>  5 8        r     r           NA     NA   NA         NA <NA>      <NA>  FALSE
#>  6 8        c     c           48      3  131.        -4 M3        <NA>  FALSE
#>  7 8        a,    a           57      2  110.        -3 m3        <NA>  FALSE
#>  8 8        g#,   g#          56      2  104.        -1 m2        <NA>  FALSE
#>  9 8        a     a           57      3  220         13 m9        <NA>  FALSE
#> 10 8        ac'e' ace         57      3  220          0 P1        <NA>  FALSE
#> # ℹ 4 more variables: bend <lgl>, dotted <int>, articulation <chr>,
#> #   annotation <chr>

Several functions are available for mapping seamlessly between and manipulating these data structures and their representations of musical information.

Noteworthy strings

It is helpful to have a deeper understanding of how this music notation syntax informs data structures and operations integrated throughout the package.

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 as input by package functions that inspect and manipulate musical information.

A bit about basic syntax

A simple character string like "c e g", or alternatively as a vector, c("c", "e", "g"), is a noteworthy string. The single lowercase letter "a" is noteworthy. So are "a_" and "a#" (flat and sharp). However, "A" is not (case sensitivity), nor is "z". Of course, as seen above, there is more valid syntax than just the lowercase musical note letters a through g and sharp and flat notation.

An important piece of syntax is the octave. In conjunction with a note, specifying a unique pitch requires the octave number, either in tick format (comma and single quote, c, c c') or integer format (c2 c c4). Octave 3 is the implicit default; there is no tick in tick format and explicitly adding the 3 in integer format is unnecessary. The pitches c d e f g a b (default octave) are the notes in the octave below middle C (c').

You’ve already seen above with the example using a music object that a noteworthy string can be one part of a more complete piece of musical information. Tick format is necessary to avoid ambiguity with respect to temporal information once two such pieces of information are merged together. For this reason, tick format is preferred in general. Tick format also matches that used by the LilyPond music engraving software, which is used by the tabr LilyPond API for anything transcription related like rendering sheet music to PDF or in R markdown documents.

For all available syntax specifications and related details see the package vignettes.

The noteworthy class

Noteworthiness can be checked on any character string. 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.

Several other generic methods are also implemented for the noteworthy class, making it easy to perform simple but powerful operations on these objects in a familiar way. While many functions will attempt to coerce a string to noteworthy, not all will and some methods are implemented specifically for the class.

x <- "g#, c d# g#c'd#'"
as_noteworthy(x)
#> <Noteworthy string>
#>   Format: space-delimited time
#>   Values: g#, c d# <g#c'd#'>

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: a, c# e <ac#'e'>

summary(x)
#> <Noteworthy string>
#>   Timesteps: 4 (3 notes, 1 chord)
#>   Octaves: tick
#>   Accidentals: sharp
#>   Format: space-delimited time
View on GitHub
GitHub Stars138
CategoryData
Updated1mo ago
Forks12

Languages

R

Security Score

85/100

Audited on Jan 25, 2026

No findings