Tracks and scores

This section puts the finishing touches on combining phrases into tracks and tracks into scores. The functions track and score have been used repeatedly throughout these tutorials out of necessity in order to demonstrate complete examples, but their use has been specific and limited and they have not been discussed.

In the examples below, phrases are added to multiple tracks, tracks are bound together, and then scores are composed of multiple tracks. Examples using different tracks, voices, and staves are considered. Then chord symbol sequences and chord charts are incorporated into scores.

Adding phrases to a track

Phrases are added to a track using the first argument to track, which strictly accepts a phrase object. Except for the briefest examples, you will typically concatenate a sequence of multiple phrases and rests into a longer section of music, usually lasting the full duration of the piece. This new single phrase object is passed to track. Taking an earlier example and breaking it up as though it were multiple phrases for illustration.

p1 <- p("c e g c' e' c' g e", 8, "5 4 3 2 1 2 3 4")
p2 <- p("g b d' g'", 8, "4 3 2 1")
p3 <- p("f a c' f'", 8, "4 3 2 1")
p4 <- p("c e g e c", "8*4 2", "5 4 3 4 5")
p_all <- glue(p1, p2, p3, p4)
track(p_all) %>% score
#> # A tibble: 1 x 7
#>   phrase   tuning         voice staff    ms_transpose ms_key tabstaff
#>   <list>   <chr>          <int> <chr>           <int> <chr>     <int>
#> 1 <phrase> e, a, d g b e'     1 treble_8            0 NA            1

This general process has been seen many times already. Now, examples are given that use the various arguments available in these functions, beginning with tracks.

Single voice

By default, a phrase passed to track is treated as part of a single voice. See below for multiple voices. By default track assigns the integer ID 1 to the voice of the phrase being transformed into a track. This can be ignored for now.

Other arguments to track include tuning, music_staff, ms_transpose and ms_key. In the vast majority of cases, tracks contain a single voice.

The simplest change to make is to suppress the music staff that appears by default above the tablature staff. ms_transpose and ms_key refer to transposition and resulting key signature of the music staff. Therefore, these two arguments are ignored whenever this staff is suppressed. You might wish to suppress it to save space in the tablature output for very simplistic rhythm patterns or melodies that are easy to interpret even without the explicit rhythm information.

track(p_all, music_staff = NA)
#> # A tibble: 1 x 6
#>   phrase   tuning         voice staff ms_transpose ms_key
#>   <list>   <chr>          <int> <chr>        <int> <chr> 
#> 1 <phrase> e, a, d g b e'     1 NA               0 NA

When the staff is not suppressed, there is the option to use the other two associated arguments to transpose the music on the staff relative to the tablature staff. This is highly useful for for example when guitar tabs are shared with musicians playing other instruments but the tablature is written with respect to capo position. This enables the music staff to be written as heard. It is not necessary to provide the new key. However, it is needed if you want to ensure that the transposed staff shows the proper key signature.

In the example below, assume the song is in the key of C. The guitarist is played with standard tuning and a capo on the second fret. This means that while the tablature is written relative to the capo, so everything still appears to be in C based on the chord shapes and fret numbers, what is heard is actually in the key of D, two semitones up. The music staff can be transposed to represent the song in D while the overall tab remains written in C with D inferred from the mention of capo position.

t1 <- track(p_all, ms_transpose = 2)
t2 <- track(p_all, ms_transpose = 2, ms_key = "d")
t1
#> # A tibble: 1 x 6
#>   phrase   tuning         voice staff    ms_transpose ms_key
#>   <list>   <chr>          <int> <chr>           <int> <chr> 
#> 1 <phrase> e, a, d g b e'     1 treble_8            2 NA
t2
#> # A tibble: 1 x 6
#>   phrase   tuning         voice staff    ms_transpose ms_key
#>   <list>   <chr>          <int> <chr>           <int> <chr> 
#> 1 <phrase> e, a, d g b e'     1 treble_8            2 d

The result above shows how this information is stored in the track tables. Here is how it looks when rendered. The tab staff remains in C, written with respect to capo 2. The key of D is inferred. However, the music staff now shows the the transposition of the music to D, which has two sharps. The notes have moved on the staff accordingly.

score(t2) %>% tab("ex22.pdf")

Multiple voices

Phrase objects may be associated with different voices, but still part of the same track. For example, it is standard to transcribe fingerstyle guitar using two voices: one for the thumb that plays the bass line and one for the fingers that play the higher melody.

These voices belong on the same music staff and tab staff and therefore must share the same track ID in tabr. The phrase objects corresponding to each voice must still be transformed into two unique track objects. The only change is that one must be explicitly assigned the voice ID 2. Make a second voice. Let the new, higher voice be voice one.

p_all2 <- p("c5 d5 e5 f5 g5", "1 2 4 4 1", "1*5")
t1 <- track(p_all2, voice = 1)
t2 <- track(p_all, voice = 2)
trackbind(t1, t2)
#> # A tibble: 2 x 7
#>   phrase   tuning         voice staff    ms_transpose ms_key tabstaff
#>   <list>   <chr>          <int> <chr>           <int> <chr>     <int>
#> 1 <phrase> e, a, d g b e'     1 treble_8            0 NA            1
#> 2 <phrase> e, a, d g b e'     2 treble_8            0 NA            2

The is the first use shown of trackbind to combine single-row track tables into multi-row track tables. Each row can be thought of as a different track. The result above is not technically correct. The two voices are intended to share the same staff, but notice that by default they are assigned incremental tabstaff integer IDs. The voice column does this here as intended based on the values supplied to each track call. However, to force these voices to share the same staff, it is necessary to override the tab staff ID as follows.

t_all <- trackbind(t1, t2, tabstaff = c(1, 1))
t_all
#> # A tibble: 2 x 7
#>   phrase   tuning         voice staff    ms_transpose ms_key tabstaff
#>   <list>   <chr>          <int> <chr>           <int> <chr>     <int>
#> 1 <phrase> e, a, d g b e'     1 treble_8            0 NA            1
#> 2 <phrase> e, a, d g b e'     2 treble_8            0 NA            1

Also note that trackbind takes any number of tracks via the ... argument. If providing tabstaff as above, it must be as a named argument. The two voices are distinguished here by different stem direction on the notes. The first voice by ID value is stem up and the second is stem down.

score(t_all) %>% tab("ex23.pdf")

Multiple tracks

Multiple voices are a special case of multiple tracks where the tab staff ID is constant and the voice ID varies, allowing the voices to be transcribed distinctly on a single staff. In general, multiple tracks are automatically designated for unique tablature and corresponding music staves. The default when track binding is to iterate the tabstaff entries for each track table row unless told otherwise and to keep a constant single voice in each tab staff (and corresponding music staff if included). This more common usage is actually simpler than using multiple voices because you can get away with specifying neither IDs for your individual tracks.

The above example redone with a single unique voice for two different sets of staves looks like the following.

t1 <- track(p_all2)
t2 <- track(p_all)
trackbind(t1, t2)
#> # A tibble: 2 x 7
#>   phrase   tuning         voice staff    ms_transpose ms_key tabstaff
#>   <list>   <chr>          <int> <chr>           <int> <chr>     <int>
#> 1 <phrase> e, a, d g b e'     1 treble_8            0 NA            1
#> 2 <phrase> e, a, d g b e'     1 treble_8            0 NA            2

Now the same tracks are simply split out to two different sets of staves.

trackbind(t1, t2) %>% score %>% tab("ex24.pdf")

Multiple voices are engraved in the output based on the order of their voice IDs. Multiple tracks assigned to different staves are engraved top to bottom based on the order they are passed to trackbind, not based on their ID values. As mentioned, these are propagated automatically when calling trackbind, except in that relatively rare case of using multiple voices per staff. Unlike voice IDs assigned in track calls, tab staff IDs are not. They do not even appear until there has been use of trackbind. The tab staff ID order is generally a consequence of the order in which the user provides the tracks to trackbind.

Below is an example with multiple tracks. The first two tracks combine as two voices on one staff set. The third track goes on a unique staff. Since the bottom track (track three) is so simple, suppress the music staff. Even though this means the bottom tab staff does not have any rhythm information associated with it, the rhythm can at least be inferred from the tab staff note spacing with respect to the notes in the first tab staff, which do have explicit rhythm information provided by the treble clef staff.

Some information is still going to be absent from the bottom staff, such as whether this rhythm is staccato, or made up of eighth notes or quarter notes. Of course, you provide this in the definition of t3 below, but it doesn’t change the fact that no one else looking at the sheet music will know for sure. Suppressing the music staves is generally a trade off between being unambiguous and saving space.

Remember to specify tabstaff in trackbind since multiple voices per staff means you cannot rely on the automatic iterated staff IDs.

t1 <- track(p_all2, voice = 1)
t2 <- track(p_all, voice = 2)
t3 <- track(p("ce*4 g,*2 f,*2 ce*3", "4*10 2", "54*4 6*4 54*3"), music_staff = NA)
t_all <- trackbind(t1, t2, t3, tabstaff = c(1, 1, 2))
t_all
#> # A tibble: 3 x 7
#>   phrase   tuning         voice staff    ms_transpose ms_key tabstaff
#>   <list>   <chr>          <int> <chr>           <int> <chr>     <int>
#> 1 <phrase> e, a, d g b e'     1 treble_8            0 NA            1
#> 2 <phrase> e, a, d g b e'     2 treble_8            0 NA            1
#> 3 <phrase> e, a, d g b e'     1 NA                  0 NA            2
score(t_all) %>% tab("ex25.pdf")

Another important fact worth mentioning is that while multiple simultaneous tracks can be bound vertically, they are never bound horizontally, or sequentially in time. Tracks are always complete segments of music with a fixed beginning and end and are never concatenated serially like phrase objects. To put it another way, trackbind is used to row bind track tables but not to column bind them.

String tuning

String tuning can be unique to each track, but this is intended to translate to each music staff. This means that entirely different tracks (destined for different music staves in the output) may be tuned differently. However, distinct voices that share the same staff should not be be passed different tunings in their respective track calls. The next example shows the change to the tuning for the first tab staff.

Rendering each of these tracks, all three look as expected given the different tuning of the guitar. By default a staff based on a non-standard tunings indicate the tuning at the beginning of the staff. For more on tunings, see the later tutorial section on non-standard tunings. Some control over displaying alternate tunings for the whole score in the rendered sheet music is available via score, touched on further below.

Supplemental music staff

Return for a moment to the music staff. Earlier it was suppressed. It was also shown how ms_tranpose and ms_key relate to it. Generally speaking, the addition of a standard music staff above the tab staff is absolutely critical for quality guitar tablature. It is the only way to provide accurate and complete rhythm information and other details not suitable to a tab staff. The tab staff does an excellent job of showing you what to play, but attempts to force it to provide more and more information regarding how to play it lead to ugly “plain text” style tabs that can be incredibly difficult to read and reason about.

tabr focuses on guitar tabs. This is why the default music staff is treble_8 for the treble clef, or G clef, transposed one octave (guitar is a transposing instrument). However, any music staff ID accepted by LilyPond can be provided; for example, bass_8 for the bass clef. Simply change the value of the music_staff argument.

track(p1, music_staff = "bass_8") %>% score %>% tab("ex27.pdf")

Adding tracks to a score

Music tracks are combined into a single score by passing a track table object to score. Like basic track usage, this has also been seen many times over by this point. There are only two other arguments that score can take, chords and chord_seq and you have seen these as well in the earlier section on chord usage in tabr. There is not much to add here other than to go over some details about how the three arguments to score behave.

Single vs. multiple tracks

For consistency, a single track is stored in a track table even though that table has only one row. All tracks are track tables. In general, track tables can have any number of rows as you have seen. Each row in a track table translates to either a new tab staff or to a combined set of two staves: one tab staff with one general music staff positioned above it. The simplest calls to score take only a single-track track table object.

Multiple tracks are bound together using trackbind. This simply row-binds multiple track tables, resulting in a multi-row track table containing a number of rows equal to the number of input tables. The input track tables may be single- or multi-track. As far as score is concerned, these are all the same. score accepts only a single track table as the first argument; multiple tracks must be bound together before passing them to score.

As you saw earlier, by default trackbind creates a sequential integer ID variable, tabstaff, in the new track table if not already present (from a previous trackbind call), assigning a unique ID to each input track table in ascending order based on the order they are passed to trackbind. One thing to note about score is that if you pass it a single-row track table that was never wrapped in trackbind, it will not have a tabstaff ID column yet. In this case, score will add the column with the ID value 1. This means that any score object will consistently have this column even if its input track table did not have it.

In the case of multiple voices on one staff discussed above, this is where those two tracks with voice IDs 1 and 2 are assigned the same staff ID by overriding the default for the tabstaff argument in trackbind.

Chords and chord sequences

score accepts the additional arguments, chords and chord_seq. See the tutorial section on chords for a refresher. The first informs the chord fretboard diagrams that make up the chord chart placed at the top center on the rendered tabs. If chords is not provided, there will simply be no chord chart inserted at the top of the first page. chord_seq informs the chord symbols places above the chord chart (if present) as well as above the topmost music or tab staff.

Both of these elements are incorporated into the final music score at the score function stage because the diagrams are associated with the entire score and not with an specific phrase or track, voice or staff. Similarly, the chord symbol sequence appears in time with the music above the topmost staff, not above each staff, and pertains to the entire score.

There is some redundancy when both of these arguments are provided to score. Both contain the names of the chords that inform the chord symbols. So for example, if you provide chord_seq, you might wonder if this makes chords redundant and unnecessary to make a chord chart, but it does not. While the names of the chord sequence vector could be used internally to define chords (and in fact, many common chord positions are predefined in LilyPond), you really do lose too much control over the specifications of the actual chord positions that inform the fretboard diagrams.

Besides, when defining a named vector for chord_seq, it is highly likely you named that sequence using a previously defined chords vector anyhow. Finally, the separation of the two arguments is not only essentially necessary for good control over definitions, but allows you to use any combination of the two. You may want a chord chart but feel no need for a chord sequence to be written out above the top staff, or vice versa. The examples below show each combination.

Score examples

To make it more interesting, these examples use the three track example from earlier. However, this time convert the bottom tab staff into a bass tab.

Finally, repeat every phrase two additional times by wrapping each phrase in rp with n = 2 for two unfolded repeats or three plays. This is simply to provide a better sense of what a rendered score tends to look like by allowing these short phrases to actually extend across a full page width of sheet music. In this first example, there is still no chord chart or chord sequence.

t1 <- track(rp(p_all2, 2), voice = 1)
t2 <- track(rp(p_all, 2), voice = 2)
t3 <- track(rp(p("c2e2*4 g1*2 f1*2 c2e2*3", "4*10 2", "32*4 4*4 32*3"), 2), tuning = "bass", music_staff = "bass_8")
t_all <- trackbind(t1, t2, t3, tabstaff = c(1, 1, 2))
t_all
#> # A tibble: 3 x 7
#>   phrase   tuning         voice staff    ms_transpose ms_key tabstaff
#>   <list>   <chr>          <int> <chr>           <int> <chr>     <int>
#> 1 <phrase> e, a, d g b e'     1 treble_8            0 NA            1
#> 2 <phrase> e, a, d g b e'     2 treble_8            0 NA            1
#> 3 <phrase> e,, a,, d, g,      1 bass_8              0 NA            2
score(t_all) %>% tab("ex28.pdf")

Notice the bass tuning automatically leads to a four line tab.

t_all remains unchanged from here forward. In the next examples, all that is needed is to alter the chords and chord_seq arguments to score. First, define these named vectors. The chord progression is C G F C. The C chords last over measures one and three. The F and G chords split the second measure, one half each.

You can define these chords however you like. They do not necessarily have to refer to the broken chords represented by the second voice of the guitar track in the output, though that would be common. Let’s say the chords in the chord chart refer generally to chords you can use to strum along, but this generic strumming is not actually shown in the tab as an explicit track because the pattern is meant to be whatever you want to make of it. Let the C chord be the open C chord, matching the melody in voice two, but the F and G chords refer to six string bar chords.

Remember that the order of the chords in chords is the order they appear in the chord chart. It is customary to show them in the order in which they first appear in a song, so C G F here, but this is certainly not a rule. The important part is that you have complete control over this. Also, because you repeated the who piece of music, you have to repeat the named chord sequence of integers similarly or the sequence chord symbols above the top staff will terminate prematurely.

chords <- chord_set(c(c = "x32o1o", g = "355433", f = "133211"))
chord_seq <- rep(setNames(c(1, 2, 2, 1), names(chords)[c(1:3, 1)]), 3)
chords
#>              c              g              f 
#> "x;3;2;o;1;o;" "3;5;5;4;3;3;" "1;3;3;2;1;1;"
chord_seq
#> c g f c c g f c c g f c 
#> 1 2 2 1 1 2 2 1 1 2 2 1

Now create a version that only adds a chord chart.

score(t_all, chords = chords) %>% tab("ex29.pdf")

The chart in the example above matches the order in which you defined your chord positions. Next, remake the score adding only the chord symbol sequence over the top staff. Remove the chord chart.

score(t_all, chord_seq = chord_seq) %>% tab("ex30.pdf")

Finally, combine both.

score(t_all, chords, chord_seq) %>% tab("ex31.pdf")

These examples demonstrate the level of control you have over this type of content, which you can elect to include or exclude depending on your preferences and how important or helpful the supplemental information is for a given song.