Create a musical phrase from character strings that define string numbers,
fret numbers and note metadata. This function is a wrapper around
phrase()
.
sf_phrase(
string,
fret = NULL,
info = NULL,
key = "c",
tuning = "standard",
to_notes = FALSE,
bar = NULL
)
sfp(
string,
fret = NULL,
info = NULL,
key = "c",
tuning = "standard",
to_notes = FALSE,
bar = NULL
)
sf_note(...)
sfn(...)
character, space-delimited or vector. String numbers
associated with notes. Alternatively, provide all information here in a
single space-delimited string and ignore fret
and info
. See details.
character, space-delimited or vector (or integer vector) of fret
numbers associated with notes. Same number of timesteps as string
.
character, space-delimited or vector (or integer vector if simple
durations) giving metadata associated with notes. Same number of timesteps as
string
.
character, key signature or just specify "sharp"
or "flat"
.
character, instrument tuning.
logical, return only the mapped notes character string rather than the entire phrase object.
character or NULL
(default). Terminates the phrase with a
bar or bar check. See details for phrase()
. Also see the LilyPond help
documentation on bar notation for all the valid options.
arguments passed to sf_phrase()
.
a phrase.
Note: This alternate specification wrapper is not receiving further support
and will be removed in a future version of tabr
.
This alternate syntax allows for specifying string/fret combinations instead
of unambiguous pitch as is used by phrase()
. In order to remove ambiguity,
it is critical to specify the instrument string tuning and key signature. It
essentially uses string
and fret
in combination with a known tuning and
key signature to generate notes
for phrase()
. info
is passed straight
through to phrase()
, as is string
once it is done being used to help
derive notes
.
See the main function phrase
for general details on phrase
construction.
phrase()
This function is a wrapper function for users not working with musical notes
(what to play), but rather just position on the guitar neck (where to play).
This approach has conveniences, but is more limiting.
In order to remove ambiguity, it is necessary to specify the instrument
tuning
and the key
signature.
In the standard approach with phrase()
you specify what to play;
specifying exactly where to play is optional, but highly recommended (by
providing string
).
With sf_phrase()
, the string
argument is of course required along with
fret
.
But any time the tuning changes, this "where to play" method breaks down and
must be redone. It is more robust to provide the string and pitch rather
than the string and fret.
The key
is additionally important because it is the only way to
indicate if accidentals should be notated as sharps or flats.
This wrapper also increases redundancy and typing. In order to specify rests
r
, silent rests s
, and tied notes ~
, these must now be providing in
parallel in both the string
and fret
arguments, whereas in the standard
method using phrase()
, they need only be provided once to notes
.
A mismatch will throw an error. Despite the redundancy, this is helpful for
ensuring proper match up between string
and fret
, which is essentially a
dual entry method that aims to reduce itself inside sf_phrase()
to a single
notes
string that is passed internally to phrase()
.
The important thing to keep in mind is that by its nature, this method of
writing out music does not lend itself well to high detail.
Tabs that are informed by nothing but string and fret number remove a lot of
important information, and those that attempt to compensate with additional
symbols in say, an ascii tab, are difficult to read.
This wrapper function providing this alternative input method to
phrase()
does its job of allowing users to create phrase objects that
are equivalent to standard phrase()
-generated objects, including rests
and ties.
But practice and comfort working with phrase()
is is highly recommended
for greater control of development support.
The function sfp()
is a convenient shorthand wrapper for sf_phrase()
.
sf_note()
and the alias sfn()
are wrappers around sf_phrase()
that
force to_notes = TRUE
.
Another way to use sf_phrase()
is to provide all musical input to
string
and ignore fret
and info
as explicit arguments.
Providing all three explicit arguments more closely mimics the inputs of
phrase()
and is useful when you have this information as three
independent sources.
However, in some cases the single-argument input method can reduce typing,
though this depends on the phrase.
More importantly, it allow you to reason about your musical inputs by time
step rather than by argument.
If you provide all three components as a single character string to the
string
argument, leaving both fret
and info
as NULL
, then
sf_phrase()
will decompose string
into its three component parts
internally.
There are some rules for single-argument input. The three components are
separated by semicolons as "string;fret;info"
.
For example, "3;7x7;4"
means begin on the third string
(infer higher number strings muted).
The frets are 7th and 7th, meaning two notes are played. When an x
is
present in the second entry it means a string is not played.
This is how it is inferred that the string numbers starting from the third
string are strings 3 and 1 rather than 3 and 2 in this example.
The 4 indicates a quarter note since it is part of the third entry where the
additional info
is specified. This is contextual. For example, an
x
here would still indicate a dead note, rather than an unplayed
string in the second entry, so this is contextual.
A bonus when using this input method is that explicit string
and
info
values persist from one timestep to the next.
Neither needs to be provided again until there is a change in value.
For example, "3;7x7;4 7x7 ;7x7;1"
repeats the string and info values
from timestep one for timestep two.
In timestep three, string numbers repeat again, but the duration changes
from quarter note to whole note.
Note that except when both string
and info
are repeating and
only fret numbers are provided (see timestep two above), two semicolons
must be present so that it is unambiguous whether the sole missing component
is a string
or info
(see timestep three).
Ambiguity would arise from a case like "4;4"
without the second semicolon.
This type of indexing was chosen over using two different delimiters.
If a rest, r
or s
, is provided for the fret
entry, then the string
entry is ignored. When using this input method, ties ~
are given in the
info entry.
See the examples for a comparison of two identical phrases specified using
both input methods for sf_phrase()
.
sf_phrase("5 4 3 2 1", "1 3 3 3 1", "8*4 1", key = "b_")
#> <Musical phrase>
#> <bes,\5>8 <f\4>8 <bes\3>8 <d'\2>8 <f'\1>1
sf_phrase("6 6 12 1 21", "133211 355333 11 (13) (13)(13)", "4 4 8 8 4",
key = "f")
#> <Musical phrase>
#> <f,\6 c\5 f\4 a\3 c'\2 f'\1>4 <g,\6 d\5 g\4 bes\3 d'\2 g'\1>4 <f'\1 c'\2>8 <f''\1>8 <c''\2 f''\1>4
sfp("6*2 1*4", "000232*2 2*4", "4 4 8*4", tuning = "dropD", key = "d")
#> <Musical phrase>
#> <d,\6 a,\5 d\4 a\3 d'\2 fis'\1>4 <d,\6 a,\5 d\4 a\3 d'\2 fis'\1>4 <fis'\1>8 <fis'\1>8 <fis'\1>8 <fis'\1>8
# compare with single-argument input
s <- "3*5 53~*3 543*2 643"
f <- "987*2 775 553 335 77~*3 545 325 210"
i <- "2*3 4. 16 4.*3 4*3"
p1 <- sfp(s, f, i)
# Nominally shorter syntax, but potentially much easier to reason about
p2 <- sfp("3;987;2*2 775 ;553;4. ;335;16 5;7x7;4.~*3 ;545;4 325 6;2x10;")
identical(p1, p2)
#> [1] TRUE