Simultaneous

Requiring an additional pattern to match at the same time, typically in another voice.

pattern alone can only describe one voice's own sequence of onsets. Chorale analysis often asks a two-voice question instead: "when the soprano does this, what does the bass do at the same time?" simultaneousWith adds that constraint on top of an ordinary query.

{
    "feature": "deg",
    "voices": "soprano",
    "pattern": [
        { "deg": "2" },
        { "deg": "1", "fermata": true }
    ],
    "simultaneousWith": [
        {
            "feature": "deg",
            "voices": "bass",
            "pattern": [
                { "deg": "4" },
                { "deg": "5" },
                { "deg": "1" }
            ]
        }
    ],
    "simultaneousAlignment": "start-end"
}

This still searches for soprano fermatas, exactly like the query would without simultaneousWith. What's added is a filter: a soprano match is only kept if the bass also has a match of its own pattern starting (see simultaneousAlignment below) at that exact same musical position.

Only the primary pattern is returned

A simultaneousWith entry only decides whether a primary match is kept. It never contributes its own matches to the results. Those stay entirely about feature/voices/pattern at the top level. simultaneousWith is a constraint, not a second search.

Fields

Each entry in the simultaneousWith array is its own small query:

FieldTypeRequiredDefaultDescription
featurestringyes—This group's own driving feature. See Query Schema.
voicesstringno"all"Which voices this group searches. See Query Schema.
patternarray of objectsyes—Same shape as the top-level pattern. See Patterns.
mintStartAtPreviousTokenbooleannoinherited(see Options)
mintAllowIntervalComplementationstring or arraynoinherited(see Options)
fbCompareExactChordbooleannoinherited(see Options)
kernIgnoreOctavebooleannoinherited(see Options)
hintReduceCompoundbooleannoinherited(see Options)
durationAllowSplitNotesbooleannoinherited(see Options)
durationAllowMergedNotesbooleannoinherited(see Options)
metweightSkipUnclassifiedbooleannoinherited(see Options)
simultaneousAlignmentstringnoinherited(see Options)

Everything below pattern is an override: leaving one out of a group falls back to the top-level query's own value of the same name, rather than a fixed default of its own. This lets one group compare chords exactly (fbCompareExactChord: true) while another in the same query still uses the default minimum-figures comparison, for example.

Several groups at once

simultaneousWith is an array. When it holds more than one entry, every group must have a match aligned with the primary match, not just one of them:

{
    "feature": "deg",
    "voices": "soprano",
    "pattern": [
        { "deg": "2" },
        { "deg": "1", "fermata": true }
    ],
    "simultaneousWith": [
        {
            "feature": "deg",
            "voices": "bass",
            "pattern": [
                { "deg": "4" },
                { "deg": "5" },
                { "deg": "1" }
            ]
        },
        {
            "feature": "mint",
            "voices": "tenor, alto",
            "pattern": [
                { "mint": "-2" },
                { "mint": "-2" },
                { "mint": "-2" }
            ],
            "mintStartAtPreviousToken": true
        }
    ],
    "simultaneousAlignment": "start-end"
}

only keeps a soprano cadence (scale degree 2 to 1, landing on a fermata) where the bass also walks scale degrees 4-5-1 underneath, and where either the tenor or the alto also has its own three-step descending run. Since simultaneousAlignment is "start-end" here, both groups have to start and end together with the soprano's match.

simultaneousAlignment

Controls which position(s) of a group's match have to line up with the primary match's: just the start, just the end, or both. See Options for the full explanation and an example. It can be set once at the top level for every group, or per group to override it.