@libraz/libcantus - v1.1.0
    Preparing search index...

    Function analyzeArrangement

    • Analyse a whole arrangement against the harmony inferred from it.

      The chord timeline and the key regions it is read against are inferred from the pooled notes of every pitched track (see chordTimelineFromNotes); pooling all voices is robust even when roles are absent or a track doubles the harmony, so it is preferred over deriving the harmony from a subset. A track marked role: 'drums' is excluded — its pitches name instruments, not harmony, and pooling them would corrupt the key, the timeline and every reading built on them. Pass harmonyTracks to restrict inference further, or timeline to analyse against a progression you already have. Zero- and negative-length notes never sound, so they are dropped at ingest and appear in neither the annotations nor the conflicts.

      Voice analysis assumes one monophonic voice at a time, so each track is first partitioned into monophonic sub-voices (a polyphonic block-chord track fans out into one sub-voice per simultaneous note; a monophonic track is unaffected). Each sub-voice is labelled note-by-note against the harmony with analyzeVoice, seeing every other sub-voice — including siblings within the same track — as its accompaniment. Every note is then re-checked with evaluateSafety at its onset and again at each chord change it sustains across, so a held note that clashes with a later chord is caught: evaluations that are not NoteSafety.Safe become conflicts, one per clashing beat, sorted worst severity first and then by beat.

      Every ordinary non-chord tone — a passing note, a neighbour, a prepared suspension — is by definition unsafe against the chord under it, so the conflict list is a report, not a fault list. Each conflict carries the note's labels and its trackIndex/originalIndex, so a caller can tell those apart and map a conflict back to the note it passed in; minSeverity narrows the list to outright dissonance.

      Parameters

      Returns ArrangementAnalysis

      The inferred harmony, per-track annotations, cadences, and conflicts.

      import { analyzeArrangement } from '@libraz/libcantus';
      const melody = [
      { pitch: 60, startBeat: 0, durationBeat: 2 },
      { pitch: 67, startBeat: 2, durationBeat: 2 },
      ];
      const { prevailingKey, conflicts } = analyzeArrangement([{ role: 'melody', notes: melody }]);
      prevailingKey.scale.rootPc; // the key held longest across the analysis
      conflicts; // notes clashing with the inferred harmony, worst severity first