kern
**kern is the Humdrum representation of the notes themselves: it's what the
chorales are transcribed in to begin with, and deg/mint/fb are all derived
from it.
Token format
For searching, a **kern token is a duration, a pitch, and an optional fermata
marker. A real token can carry plenty more than that — ties, beams, slurs, stem
direction, articulations, and other signifiers — but only these are considered
here:
- A duration
digit (or digits):
4= quarter note,8= eighth,2= half,1= whole,16= sixteenth, and so on, with one or more trailing . characters for augmentation dots (e.g.4.for a dotted quarter,4..for a double-dotted one). - A pitch letter,
repeated for register: uppercase and doubled for lower octaves (
GGis lower thanG), lowercase and doubled for higher octaves (ggis higher thang). Zero or more accidental characters (#or-, repeated for double sharps/flats, e.g.##or--) can follow immediately after the pitch letter. - …or, in place of a pitch letter, the letter
rmarking a rest. A token is either a pitch or a rest, never both. - An optional trailing
;marking a fermata.
So 4G is a quarter-note G, 8f# an eighth-note F♯ (a 4th-octave register
above 4f#'s lower relatives), 4r a quarter rest, and 2C; a half-note C
with a fermata.
Rhythm-, pitch/rest-, and fermata-optional matching
Pattern values for kern don't have to be a complete token. Any part you leave
out is treated as "matches any". In particular, leaving out ; does not require
the absence of a fermata, it simply doesn't care either way. If you
specifically want notes without a fermata, add the separate fermata key
alongside kern instead: { "kern": "4", "fermata": "false" } (see Checking
several features at once).
| Pattern value | Matches |
|---|---|
"4" | a quarter note or rest, any pitch, fermata or not |
"f#" | an F♯, any duration, fermata or not |
"r" | any rest, any duration, fermata or not |
";" | any note or rest with a fermata, any pitch/rest or duration |
"4f#" | a quarter-note F♯, fermata or not |
"4r" | a quarter rest specifically, fermata or not |
"4;" | a quarter note/rest with a fermata, any pitch |
"f#;" | an F♯ with a fermata, any duration |
"4f#;" | only a quarter-note F♯ that also has a fermata (fully specified) |
All of these see past tie and beam markup ([, ], _, L, J, …) around
the pitch letters in the actual data. "D" matches a beamed "8DL" the same as
a plain "8D". Accidentals always count as part of the pitch, and a rest is
never a match for a pitch pattern value (or vice versa).
Ties work differently: a tied note is a single onset with its combined
duration, not one onset per written fragment. A quarter tied to an eighth
(written as two tokens, e.g. "[4D" then "8DL]") sounds as a dotted quarter,
so "4" does not match it, "4." does. The tied continuation isn't a new
attack, so it never appears as a match of its own.
A repeated note is the opposite case: it really is a new attack each time, so
by default two quarters on the same pitch are two onsets and never a half note.
durationAllowSplitNotes lets a
pattern position add such repetitions up anyway, and
durationAllowMergedNotes does the
reverse, letting one half note answer two quarter-note positions.
A note an ornament takes its time from is a third case:
metweightSkipUnclassified gives
that time back, so the rhythm component of a value describes the note as the
phrase means it. A dotted quarter followed by an offbeat eighth then matches
"2", not "4.".
A pattern value containing other characters in the search query (one that
spells out tie/beam/slur markup literally, e.g. "[4D" as the value you are
searching for, not what is in the **kern data) falls back to a raw,
markup-sensitive string comparison instead of this component-wise matching.
Comparing pitches
A pitch can also be compared with a comparison, where a greater note is a higher one:
{ "kern": { "operator": "gt", "value": "a" } }
matches every note higher than the a above middle c. The value is a pitch like the
ones above, written without rhythm or fermata ("4a" is not a pitch to compare with,
use the duration key for the rhythm).
- Pitches are compared by sound, in semitones including the octave.
"a"is not"A", and"c#"and"d-"are equally high. - A rest has no pitch: it is neither higher nor lower than anything. With
!kernit does count as "not higher than a". kernIgnoreOctavehas no effect on comparisons.
Mixing specificity across positions
Each position in a pattern is matched independently, so a fully specified token can be followed by a rhythm-only one, then a fermata-only one, and so on:
{
"feature": "kern",
"pattern": [
{ "kern": "4f#" },
{ "kern": "4" },
{ "kern": ";" }
]
}
matches a quarter-note F♯, then any quarter note, then any note with a fermata. Pin down exactly as much (or as little) as matters at each position.
Using it in a pattern
{
"feature": "kern",
"pattern": [
{ "kern": "g" },
{ "kern": "a" },
{ "kern": "b-" }
]
}
matches a G, A and B♭ in a row in that 4th-octave register, any duration, fermata or not. See
Patterns for OR-lists, wildcards, multi-feature positions, and
negation, all of which work the same way for kern as for any other feature.
To match a pitch class in any register instead, such as "g" matching GG,
G, g, gg, and so on, set the query option
kernIgnoreOctave.
Driving a search off kern directly is most useful for literal note-for-note
searches; for anything about scale degree, melodic shape, harmony, or beat
strength, deg, mint, fb, and metweight do the analysis for you.