Simultaneous
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:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
feature | string | yes | — | This group's own driving feature. See Query Schema. |
voices | string | no | "all" | Which voices this group searches. See Query Schema. |
pattern | array of objects | yes | — | Same shape as the top-level pattern. See Patterns. |
mintStartAtPreviousToken | boolean | no | inherited | (see Options) |
mintAllowIntervalComplementation | string or array | no | inherited | (see Options) |
fbCompareExactChord | boolean | no | inherited | (see Options) |
kernIgnoreOctave | boolean | no | inherited | (see Options) |
hintReduceCompound | boolean | no | inherited | (see Options) |
durationAllowSplitNotes | boolean | no | inherited | (see Options) |
durationAllowMergedNotes | boolean | no | inherited | (see Options) |
metweightSkipUnclassified | boolean | no | inherited | (see Options) |
simultaneousAlignment | string | no | inherited | (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.