Features

kern

Searching the raw notes, pitch and rhythm.

**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 (GG is lower than G), lowercase and doubled for higher octaves (gg is higher than g). 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 r marking 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 valueMatches
"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 !kern it does count as "not higher than a".
  • kernIgnoreOctave has 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.