-
With Subset
-
-
The subset
argument indicates a subset of the data which
-we should evaluate “within.” There subset
argument must be
-an expression which evaluates to a logical vector (TRUE
of
-FALSE
). The main command is then evaluated wherever the
-subset
expression evaluates to TRUE
.
-
Let’s try it with our tabling example. Maybe we want to table only
-tokens in the first spine:
-
with(chorales,
- kern(Token) |> table() |> sort() |> tail(n = 10),
- subset = Spine == 1)
->
-> GG C# A G AA F# BB C D E
-> 29 30 36 36 44 44 48 57 70 85
-
We only see the low notes, which is what we’d expect from the bass
-voice.
-
What about this, let’s only tabulate the even-numbered bars: For
-datasets which have measures indicated (with =
tokens), the
-Bar
field is integers counting these bars within each
-piece. If we want even numbers, we can ask where is Bar
-modulo 2 zero?: Bar %% 2 == 0
.
-
with(chorales,
- kern(Token) |> table() |> sort() |> tail(n = 10),
- subset = Bar %% 2 == 0)
->
-> G c f# A B b d g a e
-> 41 53 57 59 62 63 63 72 82 111
-
If we use the subset
argument with within
,
-parts of the data which don’t match the within
expression
-are returned as null:
-
-within(chorales,
- Pitch <- pitch(Token, simple = TRUE),
- subset = Spine == 1)
-> ############################# vvv chor001.krn vvv #############################
-> 1: !!!COM: Bach, Johann Sebastian
-> 2: !!!CDT: 1685/02/21/-1750/07/28/
-> 3: !!!OTL@@DE: Aus meines Herzens Grunde
-> 4: !!!OTL@EN: From the Depths of My Heart
-> 5: !!!SCT: BWV 269
-> 6: !!!PC#: 1
-> 7: !!!AGN: chorale
-> 8: **pitch **pitch **pitch **pitch
-> 9: *ICvox *ICvox *ICvox *ICvox
-> 10: *Ibass *Itenor *Ialto *Isoprn
-> 11: *I"Bass *I"Tenor *I"Alto *I"Soprano
-> 12: *>[A,A,B] *>[A,A,B] *>[A,A,B] *>[A,A,B]
-> 13: *>norep[A,B] *>norep[A,B] *>norep[A,B] *>norep[A,B]
-> 14: *>A *>A *>A *>A
-> 15: *clefF4 *clefGv2 *clefG2 *clefG2
-> 16: *k[f#] *k[f#] *k[f#] *k[f#]
-> 17: *G: *G: *G: *G:
-> 18: *M3/4 *M3/4 *M3/4 *M3/4
-> 19: *MM100 *MM100 *MM100 *MM100
-> 20: G . . .
-> 21: =1 =1 =1 =1
-> 22: G . . .
-> 23: E . . .
-> 24: . . . .
-> 25: F# . . .
-> 26: =2 =2 =2 =2
-> 27: G . . .
-> 28: D . . .
-> 29: . . . .
-> 30: E . . .
-> 31: =3 =3 =3 =3
-> 32: C . . .
-> 33: . . . .
-> 34: B . . .
-> 35: A . . .
-> 36: G . . .
-> 37: =4 =4 =4 =4
-> 38: D . . .
-> 39: G . . .
-> 40: =5 =5 =5 =5
-> 41-133:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-> ############################# ^^^ chor001.krn ^^^ #############################
->
-> (8 more pieces...)
->
-> ############################# vvv chor010.krn vvv #############################
-> 1-60:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-> 61: A . . .
-> 62: A . . .
-> 63: =9 =9 =9 =9
-> 64: E . . .
-> 65: D . . .
-> 66: C . . .
-> 67: B . . .
-> 68: . . . .
-> 69: C . . .
-> 70: =10 =10 =10 =10
-> 71: D . . .
-> 72: . . . .
-> 73: D . . .
-> 74: . . . .
-> 75: G . . .
-> 76: =11 =11 =11 =11
-> 77: C . . .
-> 78: A . . .
-> 79: E . . .
-> 80: . . . .
-> 81: =12 =12 =12 =12
-> 82: F . . .
-> 83: C . . .
-> 84: Bb . . .
-> 85: A . . .
-> 86: =13 =13 =13 =13
-> 87: G# . . .
-> 88: A . . .
-> 89: E . . .
-> 90: == == == ==
-> 91: *- *- *- *-
-> 92: !!!hum2abc: -Q ''
-> 93: !!!title: @{PC#}. @{OTL@@DE}
-> 94: !!!YOR1: 371 vierstimmige Choralgesänge von Johann Sebastian B***
-> 95: !!!YOR2: 4th ed. by Alfred Dörffel (Leipzig: Breitkopf und H&a***
-> 96: !!!YOR2: c.1875). 178 pp. Plate "V.A.10". reprint: J.S. Bach, 371 ***
-> 97: !!!YOR4: Chorales (New York: Associated Music Publishers, Inc., c.1***
-> 98: !!!SMS: B&H, 4th ed, Alfred Dörffel, c.1875, plate V.A.10
-> 99: !!!EED: Craig Stuart Sapp
-> 100: !!!EEV: 2009/05/22
-> ############################# ^^^ chor010.krn ^^^ #############################
-> (***four global comments truncated due to screen size***)
->
-> humdrumR corpus of ten pieces.
-> Data fields:
-> Token :: character
-> *Pitch :: character (**pitch tokens)
-
Notice, our new Pitch
field is NULL
in all
-spine except spine 1.
-
-
Or else…
-
-
In many cases when using subset
we’d like to do
-something with, or at least keep, the “other” part of the data—the
-complement of the subset. We can do this by expressing a “complement”
-expression. The idea is that we say “evaluate X where Y is true,
-otherwise evaluate this instead.” This is easiest to understand if we
-use our within
example from above. Maybe we want to
-calculate the simple pitch of the first spine, but leave the other
-spines unchanged:
-
-within(chorales,
- Pitch <- pitch(Token, simple = TRUE),
- subset = Spine == 1,
- complement = Token)
-> ############################# vvv chor001.krn vvv #############################
-> 1: !!!COM: Bach, Johann Sebastian
-> 2: !!!CDT: 1685/02/21/-1750/07/28/
-> 3: !!!OTL@@DE: Aus meines Herzens Grunde
-> 4: !!!OTL@EN: From the Depths of My Heart
-> 5: !!!SCT: BWV 269
-> 6: !!!PC#: 1
-> 7: !!!AGN: chorale
-> 8: **pitch **pitch **pitch **pitch
-> 9: *ICvox *ICvox *ICvox *ICvox
-> 10: *Ibass *Itenor *Ialto *Isoprn
-> 11: *I"Bass *I"Tenor *I"Alto *I"Soprano
-> 12: *>[A,A,B] *>[A,A,B] *>[A,A,B] *>[A,A,B]
-> 13: *>norep[A,B] *>norep[A,B] *>norep[A,B] *>norep[A,B]
-> 14: *>A *>A *>A *>A
-> 15: *clefF4 *clefGv2 *clefG2 *clefG2
-> 16: *k[f#] *k[f#] *k[f#] *k[f#]
-> 17: *G: *G: *G: *G:
-> 18: *M3/4 *M3/4 *M3/4 *M3/4
-> 19: *MM100 *MM100 *MM100 *MM100
-> 20: G 4B 4d 4g
-> 21: =1 =1 =1 =1
-> 22: G 4B 4d 2g
-> 23: E 8cL 4e .
-> 24: . 8BJ . .
-> 25: F# 4A 4d 4dd
-> 26: =2 =2 =2 =2
-> 27: G 4G 2d 4.b
-> 28: D 4F# . .
-> 29: . . . 8a
-> 30: E 4G 4B 4g
-> 31: =3 =3 =3 =3
-> 32: C 8cL 8eL 4.g
-> 33: . 8BJ 8d .
-> 34: B 4c 8e .
-> 35: A . 8f#J 8a
-> 36: G 4d 4g 4b
-> 37: =4 =4 =4 =4
-> 38: D 2d; 2f#; 2a;
-> 39: G 4d 4g 4b
-> 40: =5 =5 =5 =5
-> 41-133:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-> ############################# ^^^ chor001.krn ^^^ #############################
->
-> (8 more pieces...)
->
-> ############################# vvv chor010.krn vvv #############################
-> 1-60:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-> 61: A 2c; 2e; 2a;
-> 62: A 2e 2a 2cc
-> 63: =9 =9 =9 =9
-> 64: E 4e 4g 4b
-> 65: D 4e 4g 4cc
-> 66: C . . .
-> 67: B 4d 8gL 4dd
-> 68: . . 8fJ .
-> 69: C 4c 4e 4g
-> 70: =10 =10 =10 =10
-> 71: D 8F# 4d 4b
-> 72: . 4G . .
-> 73: D . 4c 4a
-> 74: . 8F# . .
-> 75: G 2G; 2B; 2g;
-> 76: =11 =11 =11 =11
-> 77: C 2G 2e 2g
-> 78: A 4A 4e 4cc
-> 79: E 4G# 8eL 4b
-> 80: . . 8dJ .
-> 81: =12 =12 =12 =12
-> 82: F 4A 4c 4a
-> 83: C 4G 4c 4e
-> 84: Bb 4G [2d 4g
-> 85: A 4A . 4f
-> 86: =13 =13 =13 =13
-> 87: G# 4B 4d] 1e;
-> 88: A 4A 4c .
-> 89: E 2G#X; 2B; .
-> 90: == == == ==
-> 91: *- *- *- *-
-> 92: !!!hum2abc: -Q ''
-> 93: !!!title: @{PC#}. @{OTL@@DE}
-> 94: !!!YOR1: 371 vierstimmige Choralgesänge von Johann Sebastian B***
-> 95: !!!YOR2: 4th ed. by Alfred Dörffel (Leipzig: Breitkopf und H&a***
-> 96: !!!YOR2: c.1875). 178 pp. Plate "V.A.10". reprint: J.S. Bach, 371 ***
-> 97: !!!YOR4: Chorales (New York: Associated Music Publishers, Inc., c.1***
-> 98: !!!SMS: B&H, 4th ed, Alfred Dörffel, c.1875, plate V.A.10
-> 99: !!!EED: Craig Stuart Sapp
-> 100: !!!EEV: 2009/05/22
-> ############################# ^^^ chor010.krn ^^^ #############################
-> (***four global comments truncated due to screen size***)
->
-> humdrumR corpus of ten pieces.
-> Data fields:
-> Token :: character
-> *Pitch :: character (**pitch tokens)
-
This pattern, with comp = Token
is quite common.
-
-
-
With Subgroups
-
-
The by
keyword arguments is short for “group by.” We can
-indicate a field in our data to group the data by—our main call will
-then be applied separately to each group, and all the groups will be
-returned.
-
Let’s try it with our tabling example. Let’s group the data by spine,
-so we tabulate each spine of data (voice) separately!
-
with(chorales,
- kern(Token) |> table() |> sort() |> tail(n = 10),
- by = Spine)
-> $`1`
->
-> GG C# A G AA F# BB C D E
-> 29 30 36 36 44 44 48 57 70 85
->
-> $`2`
->
-> B- F# G# c# G e A c B d
-> 17 20 29 34 35 75 76 83 85 88
->
-> $`3`
->
-> B d# b d g# f a f# g e
-> 16 16 19 43 44 50 67 83 88 121
->
-> $`4`
->
-> b- g# e ee cc# g dd cc a b
-> 15 15 17 25 36 42 48 68 93 115
-
We get four different tables, one of each spine. If we want
-to make multiple plots, we can just add barplot
like
-before.
-
-
-
-
Let’s try something slightly different: Since our four spines
-represent bass, tenor, alto, and soprano voices (in that order) I’d
-expect that average pitch of each spine to be significantly different.
-Let’s convert our pitch data to semitones (using semits
)
-and add a call to the base-R function mean
: Watch
-
with(chorales,
- semits(Token) |> mean(),
- by = Spine)
-> 1 2 3 4
-> -9.6692308 -0.1143317 5.6065041 10.5672192
-
Oops, that didn’t work! It’s because some of our Token
-data are rests, like 4r
. The semits
function
-doesn’t know how to read 4r
so it returns an
-NA
value. Don’t worry, this is an easy fix, and a good
-lesson for data analysis in general and R in particular. We always need
-to keep in mind what data is “missing” or Not Applicable
-(NA
). Most R math functions have an option to ignore
-missing data by setting na.rm = TRUE
(NA remove):
-
with(chorales,
- semits(Token) |> mean(na.rm = TRUE),
- by = Spine)
-> 1 2 3 4
-> -9.6692308 -0.1143317 5.6065041 10.5672192
-
That’s what we expected! Of course, we might prefer a plot.
-
-with(chorales,
- semits(Token) |> mean(na.rm = TRUE),
- by = Spine) |> barplot(names.arg = c('Bass', 'Tenor', 'Alto', 'Soprano'),
- main = 'Mean Pitch by Voice',
- ylab = 'Semitones')
-
-
Notice that we did something differently here! We don’t want to make
-a separate plot of each group-by calculation—that would just be
-a single number for each spine. We want to make a plot of all four
-numbers, so we put the barplot
call after
-(outside) the with
call. Notice we can also control the
-labels for our barplot using the names.arg
argument.
-
Maybe we want to inspect a whole histogram of the pitches in each
-voice. We can use the base-R hist
function; Since we want a
-histogram of each spine, we will want to put hist
-“inside” the call to with
again:
-
-with(chorales,
- semits(Token) |> hist(xlim = c(-24, 24), main = Instrument[1]),
- by = Spine)
-
-
Pro tips: by setting the xlim
(x-limit) argument, we
-make sure that all four barplots cover the same ranges of pitches, so
-they are comparable. We also set the main argument (figure title) using
-the Instrument
field, which gives us the names of each
-instrument. That’s right, we can refer to any/all fields in the humdrum
-data! (Not all datasets have this tandem interpretation, so it wouldn’t
-always work.)
-
-
Advanced Grouping
-
-
We can group our data by any arbitrary grouping in our data. In fact
-the by
keyword argument can be a complex expression, as
-long as its output is the same length as its input. For example, maybe
-we’d like to reproduce our histograms, but lumping the male (bass/tenor)
-and female (alto/soprano) voices together.
-
-
-
The expression Spine < 3
returns FALSE
-for spines 1 and 2 (bass and tenor) and TRUE
for spines 3
-and 4. These two categories (FALSE
and TRUE
)
-are then used to group the data.
-
-
-
Recycling results
-
-
In some cases, we’d like to perform a command within
our
-data which might output a smaller vector than in the input, including a
-single value, but we still want to reconstruct the data fully. In R,
-this is usually called “recycling”—i.e., repeating a value until it
-matches a certain length. When using with
or
-within
, we can cause our results to be recycled to the full
-field length by using the recycle
argument for our
-expression. This is useful if you want to group by something, and fill
-each group with the same value:
-
-within(chorales,
- Semits <- semits(Token)) -> chorales
-
-within(chorales,
- recycle = BarBassNote <- min(Semits),
- by = list(File, Bar)) -> chorales
-
-chorales
-> ############################# vvv chor001.krn vvv #############################
-> 1: !!!COM: Bach, Johann Sebastian
-> 2: !!!CDT: 1685/02/21/-1750/07/28/
-> 3: !!!OTL@@DE: Aus meines Herzens Grunde
-> 4: !!!OTL@EN: From the Depths of My Heart
-> 5: !!!SCT: BWV 269
-> 6: !!!PC#: 1
-> 7: !!!AGN: chorale
-> 8: **semits **semits **semits **semits
-> 9: *ICvox *ICvox *ICvox *ICvox
-> 10: *Ibass *Itenor *Ialto *Isoprn
-> 11: *I"Bass *I"Tenor *I"Alto *I"Soprano
-> 12: *>[A,A,B] *>[A,A,B] *>[A,A,B] *>[A,A,B]
-> 13: *>norep[A,B] *>norep[A,B] *>norep[A,B] *>norep[A,B]
-> 14: *>A *>A *>A *>A
-> 15: *clefF4 *clefGv2 *clefG2 *clefG2
-> 16: *k[f#] *k[f#] *k[f#] *k[f#]
-> 17: *G: *G: *G: *G:
-> 18: *M3/4 *M3/4 *M3/4 *M3/4
-> 19: *MM100 *MM100 *MM100 *MM100
-> 20: -17 -17 -17 -17
-> 21: =1 =1 =1 =1
-> 22: -8 -8 -8 -8
-> 23: -8 -8 -8 .
-> 24: . -8 . .
-> 25: -8 -8 -8 -8
-> 26: =2 =2 =2 =2
-> 27: -10 -10 -10 -10
-> 28: -10 -10 . .
-> 29: . . . -10
-> 30: -10 -10 -10 -10
-> 31: =3 =3 =3 =3
-> 32: -17 -17 -17 -17
-> 33: . -17 -17 .
-> 34: -17 -17 -17 .
-> 35: -17 . -17 -17
-> 36: -17 -17 -17 -17
-> 37: =4 =4 =4 =4
-> 38: -17 -17 -17 -17
-> 39: -17 -17 -17 -17
-> 40: =5 =5 =5 =5
-> 41-133:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-> ############################# ^^^ chor001.krn ^^^ #############################
->
-> (8 more pieces...)
->
-> ############################# vvv chor010.krn vvv #############################
-> 1-60:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-> 61: -15 -15 -15 -15
-> 62: -15 -15 -15 -15
-> 63: =9 =9 =9 =9
-> 64: -13 -13 -13 -13
-> 65: -13 -13 -13 -13
-> 66: -13 . . .
-> 67: -13 -13 -13 -13
-> 68: . . -13 .
-> 69: -13 -13 -13 -13
-> 70: =10 =10 =10 =10
-> 71: -17 -17 -17 -17
-> 72: . -17 . .
-> 73: -17 . -17 -17
-> 74: . -17 . .
-> 75: -17 -17 -17 -17
-> 76: =11 =11 =11 =11
-> 77: -15 -15 -15 -15
-> 78: -15 -15 -15 -15
-> 79: -15 -15 -15 -15
-> 80: . . -15 .
-> 81: =12 =12 =12 =12
-> 82: -15 -15 -15 -15
-> 83: -15 -15 -15 -15
-> 84: -15 -15 -15 -15
-> 85: -15 -15 . -15
-> 86: =13 =13 =13 =13
-> 87: -20 -20 -20 -20
-> 88: -20 -20 -20 .
-> 89: -20 -20 -20 .
-> 90: == == == ==
-> 91: *- *- *- *-
-> 92: !!!hum2abc: -Q ''
-> 93: !!!title: @{PC#}. @{OTL@@DE}
-> 94: !!!YOR1: 371 vierstimmige Choralgesänge von Johann Sebastian B***
-> 95: !!!YOR2: 4th ed. by Alfred Dörffel (Leipzig: Breitkopf und H&a***
-> 96: !!!YOR2: c.1875). 178 pp. Plate "V.A.10". reprint: J.S. Bach, 371 ***
-> 97: !!!YOR4: Chorales (New York: Associated Music Publishers, Inc., c.1***
-> 98: !!!SMS: B&H, 4th ed, Alfred Dörffel, c.1875, plate V.A.10
-> 99: !!!EED: Craig Stuart Sapp
-> 100: !!!EEV: 2009/05/22
-> ############################# ^^^ chor010.krn ^^^ #############################
-> (***four global comments truncated due to screen size***)
->
-> humdrumR corpus of ten pieces.
-> Data fields:
-> Token :: character
-> Pitch :: character (**pitch tokens)
-> Semits :: integer (**semits tokens)
-> *BarBassNote :: integer (**semits tokens)
-
What did this command do? It looks at every bar in each file and
-finds the lowest note, then “fills” all the notes in that bar with that
-same, single, note. We could then calculate the harmonic interval above
-the bar’s bass note:
-
-within(chorales,
- Semits - BarBassNote)
-> ############################# vvv chor001.krn vvv #############################
-> 1: !!!COM: Bach, Johann Sebastian
-> 2: !!!CDT: 1685/02/21/-1750/07/28/
-> 3: !!!OTL@@DE: Aus meines Herzens Grunde
-> 4: !!!OTL@EN: From the Depths of My Heart
-> 5: !!!SCT: BWV 269
-> 6: !!!PC#: 1
-> 7: !!!AGN: chorale
-> 8: **semits **semits **semits **semits
-> 9: *ICvox *ICvox *ICvox *ICvox
-> 10: *Ibass *Itenor *Ialto *Isoprn
-> 11: *I"Bass *I"Tenor *I"Alto *I"Soprano
-> 12: *>[A,A,B] *>[A,A,B] *>[A,A,B] *>[A,A,B]
-> 13: *>norep[A,B] *>norep[A,B] *>norep[A,B] *>norep[A,B]
-> 14: *>A *>A *>A *>A
-> 15: *clefF4 *clefGv2 *clefG2 *clefG2
-> 16: *k[f#] *k[f#] *k[f#] *k[f#]
-> 17: *G: *G: *G: *G:
-> 18: *M3/4 *M3/4 *M3/4 *M3/4
-> 19: *MM100 *MM100 *MM100 *MM100
-> 20: 0 16 19 24
-> 21: =1 =1 =1 =1
-> 22: 3 7 10 15
-> 23: 0 8 12 .
-> 24: . 7 . .
-> 25: 2 5 10 22
-> 26: =2 =2 =2 =2
-> 27: 5 5 12 21
-> 28: 0 4 . .
-> 29: . . . 19
-> 30: 2 5 9 17
-> 31: =3 =3 =3 =3
-> 32: 5 17 21 24
-> 33: . 16 19 .
-> 34: 4 17 21 .
-> 35: 2 . 23 26
-> 36: 0 19 24 28
-> 37: =4 =4 =4 =4
-> 38: 7 19 23 26
-> 39: 0 19 24 28
-> 40: =5 =5 =5 =5
-> 41-133:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-> ############################# ^^^ chor001.krn ^^^ #############################
->
-> (8 more pieces...)
->
-> ############################# vvv chor010.krn vvv #############################
-> 1-60:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-> 61: 0 15 19 24
-> 62: 12 19 24 27
-> 63: =9 =9 =9 =9
-> 64: 5 17 20 24
-> 65: 3 17 20 25
-> 66: 1 . . .
-> 67: 0 15 20 27
-> 68: . . 18 .
-> 69: 1 13 17 20
-> 70: =10 =10 =10 =10
-> 71: 7 11 19 28
-> 72: . 12 . .
-> 73: 7 . 17 26
-> 74: . 11 . .
-> 75: 0 12 16 24
-> 76: =11 =11 =11 =11
-> 77: 3 10 19 22
-> 78: 0 12 19 27
-> 79: 7 11 19 26
-> 80: . . 17 .
-> 81: =12 =12 =12 =12
-> 82: 8 12 15 24
-> 83: 3 10 15 19
-> 84: 1 10 17 22
-> 85: 0 12 . 20
-> 86: =13 =13 =13 =13
-> 87: 4 19 22 24
-> 88: 5 17 20 .
-> 89: 0 16 19 .
-> 90: == == == ==
-> 91: *- *- *- *-
-> 92: !!!hum2abc: -Q ''
-> 93: !!!title: @{PC#}. @{OTL@@DE}
-> 94: !!!YOR1: 371 vierstimmige Choralgesänge von Johann Sebastian B***
-> 95: !!!YOR2: 4th ed. by Alfred Dörffel (Leipzig: Breitkopf und H&a***
-> 96: !!!YOR2: c.1875). 178 pp. Plate "V.A.10". reprint: J.S. Bach, 371 ***
-> 97: !!!YOR4: Chorales (New York: Associated Music Publishers, Inc., c.1***
-> 98: !!!SMS: B&H, 4th ed, Alfred Dörffel, c.1875, plate V.A.10
-> 99: !!!EED: Craig Stuart Sapp
-> 100: !!!EEV: 2009/05/22
-> ############################# ^^^ chor010.krn ^^^ #############################
-> (***four global comments truncated due to screen size***)
->
-> humdrumR corpus of ten pieces.
-> Data fields:
-> Token :: character
-> Pitch :: character (**pitch tokens)
-> Semits :: integer (**semits tokens)
-> BarBassNote :: integer (**semits tokens)
-> *Result1 :: integer (**semits tokens)
-
-with(chorales, hist(Semits - BarBassNote))
-
-