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.
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.
notesC <- "c e g c' e' c' g e g b d' g' f a c' f' c e g e c"
strings <- "5 4 3 2 1 2 3 4 4 3 2 1 4 3 2 1 5 4 3 4 5"
p1 <- p(notesC, "8*20 2", strings)
track(p1)
#> # A tibble: 1 × 7
#> phrase clef key tab tuning voice lyrics
#> <list> <chr> <chr> <lgl> <chr> <int> <chr>
#> 1 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 1 NA
This general process has been seen many times already. Below,
examples are given that use the various arguments available in these
functions, beginning with tracks. Briefly before exploring these
arguments, note that track()
is equivalent to
track_guitar()
and has appropriate default arguments.
However, other wrappers around track()
are available that
take different defaults. track_bass()
defaults to standard
four-string bass tuning and includes the tab staff. For sheet music
treble clef and bass clef tracks without any tablature staff, you can
use track_tc()
and track_bc()
,
respectively.
#> # A tibble: 2 × 8
#> phrase clef key tab tuning voice lyrics id
#> <list> <chr> <chr> <lgl> <chr> <int> <chr> <int>
#> 1 <phrase [1]> treble NA FALSE e,a,dgbe' 1 NA 1
#> 2 <phrase [1]> bass NA FALSE e,a,dgbe' 1 NA 2
By default, a phrase passed to a track_*
function is
treated as part of a single voice. See below for multiple voices. These
functions assign the integer ID 1
to the voice of the
phrase being transformed into a track. This can be ignored for now.
Other arguments, depending on the context of the particular track
function, include clef
, key
, tab
,
tuning
and lyrics
. For most use cases, tracks
are likely to contain a single voice.
You can suppress the tablature staff with tab = FALSE
or
the music staff with clef = NA
, but not both. When both are
included the music staff with the given clef symbol appears above the
tablature staff. key
specifies the key signature of the
music staff, ignored when the staff is suppressed.
tab = FALSE
suppresses the tab staff. tuning
specifies the string tuning of the tab staff, ignored when the staff is
suppressed.
#> # A tibble: 2 × 8
#> phrase clef key tab tuning voice lyrics id
#> <list> <chr> <chr> <lgl> <chr> <int> <chr> <int>
#> 1 <phrase [1]> NA NA TRUE e,a,dgbe' 1 NA 1
#> 2 <phrase [1]> treble_8 g FALSE e,a,dgbe' 1 NA 2
Multiple tracks are automatically designated for unique staves. The
default when track binding is to iterate the id
entries for
each track table row unless you specify otherwise and to keep a constant
single voice
in each staff.
#> # A tibble: 2 × 8
#> phrase clef key tab tuning voice lyrics id
#> <list> <chr> <chr> <lgl> <chr> <int> <chr> <int>
#> 1 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 1 NA 1
#> 2 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 1 NA 2
Here is the output containing two tracks; in this case two sets of music/tab staff pairs since no staves have been suppressed for either track.
In the example below, assume the song is in the key of C. The guitar is played with standard tuning and a capo on the second fret. This means that while the tablature is written relative to the capo and appears to be in C based on the chord shapes and fret numbers, it sounds like it is in D, two semitones up. However, say you want the music staff to be written in D as heard. This requires two tracks, but in this case, suppress the music staff for one track and the tab staff for the other track.
The necessary first step is to transpose notes with
transpose()
prior to converting them to LilyPond syntax
with phrase()
.
p2 <- tp(notesC, 2, key = "d") |> p("8*20 2", strings)
t1 <- track(p2, key = "d", tab = FALSE)
t2 <- track(p1, clef = NA)
trackbind(t1, t2)
#> # A tibble: 2 × 8
#> phrase clef key tab tuning voice lyrics id
#> <list> <chr> <chr> <lgl> <chr> <int> <chr> <int>
#> 1 <phrase [1]> treble_8 d FALSE e,a,dgbe' 1 NA 1
#> 2 <phrase [1]> NA NA TRUE e,a,dgbe' 1 NA 2
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. Simply
setting the key signature of the staff with key
would not
have transposed the notes themselves.
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. 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.
p2 <- p("c'' d'' e'' f'' g''", "1 2 4 4 1", 5)
t1 <- track(p2, voice = 1)
t2 <- track(p1, voice = 2)
trackbind(t1, t2)
#> # A tibble: 2 × 8
#> phrase clef key tab tuning voice lyrics id
#> <list> <chr> <chr> <lgl> <chr> <int> <chr> <int>
#> 1 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 1 NA 1
#> 2 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 2 NA 2
The is the first use shown of trackbind()
to combine
tracks (single-row track tables) into multi-row track tables. The result
above is not the intended result. The two voices are intended to share
the same staff, but notice that by default they are assigned incremental
track IDs in the id
column, just as in previous examples.
The voice
increments 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 track ID
as follows.
#> # A tibble: 2 × 8
#> phrase clef key tab tuning voice lyrics id
#> <list> <chr> <chr> <lgl> <chr> <int> <chr> <int>
#> 1 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 1 NA 1
#> 2 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 2 NA 1
Also note that trackbind()
takes any number of tracks
via the ...
argument. If providing id
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.
Multiple voices and tracks are engraved in the output based on the
order of the values in voice
and id
,
respectively. The id
column is not created until there has
been a call to trackbind()
, or score()
in the
case of a single track input where no prior call to
trackbind()
was needed.
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 id
in trackbind()
since
multiple voices per staff means you cannot rely on the automatic
iterated track IDs.
t1 <- track(p2, voice = 1)
t2 <- track(p1, voice = 2)
t3 <- track(p("ce*4 g,*2 f,*2 ce*3", "4*10 2", "54*4 6*4 54*3"), clef = NA)
t_all <- trackbind(t1, t2, t3, id = c(1, 1, 2))
t_all
#> # A tibble: 3 × 8
#> phrase clef key tab tuning voice lyrics id
#> <list> <chr> <chr> <lgl> <chr> <int> <chr> <int>
#> 1 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 1 NA 1
#> 2 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 2 NA 1
#> 3 <phrase [1]> NA NA TRUE e,a,dgbe' 1 NA 2
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.
String tuning can be unique to each track, but this is intended to
translate to a tab staff. This means that entirely different tracks
(destined for different tab 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.
x <- p("e, b, e g b e'", 8)
t1 <- track(x)
t2 <- track(x, tuning = "dropD")
t3 <- track(x, tuning = "dropC")
Rendering each of these tracks, all three look as expected given the different string tuning. By default a staff based on a non-standard tunings indicates the tuning at the beginning of the staff. For more on tunings, see the later tutorial section on non-standard tunings. Some control over display of alternate tunings for the whole score in the rendered sheet music is available via the various rendering functions.
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.
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 a new music and/or tablature staff or to a combined set of two staves.
For a single track not wrapped in a call to trackbind()
,
the id
column does not yet exist. In this case
score()
creates it and assigns that value 1
.
score()
accepts only a single track table as the first
argument; multiple tracks must be bound together with
trackbind()
before passing them to
score()
.
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.
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.
tuning = "bass"
in track()
. This
is shorthand for standard four string bass tuning. For more details on
tunings and other instruments, see the later tutorial section on strings
and tunings.music_staff = "bass_8"
.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(p2, 2), voice = 1)
t2 <- track(rp(p1, 2), voice = 2)
t3 <- track(rp(p("c,e,*4 g,,*2 f,,*2 c,e,*3", "4*10 2", "32*4 4*4 32*3"), 2),
clef = "bass_8", tuning = "bass")
t_all <- trackbind(t1, t2, t3, id = c(1, 1, 2))
t_all
#> # A tibble: 3 × 8
#> phrase clef key tab tuning voice lyrics id
#> <list> <chr> <chr> <lgl> <chr> <int> <chr> <int>
#> 1 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 1 NA 1
#> 2 <phrase [1]> treble_8 NA TRUE e,a,dgbe' 2 NA 1
#> 3 <phrase [1]> bass_8 NA TRUE e,,a,,d,g, 1 NA 2
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.
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.
Finally, combine both.
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.