@libraz/libcantus - v0.9.3
    Preparing search index...

    Function analyzeArrangement

    • Analyse a whole arrangement against a single inferred harmony.

      The chord timeline and key are inferred from the pooled notes of every 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. 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.

      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 { key, conflicts } = analyzeArrangement([{ role: 'melody', notes: melody }]);
      conflicts; // notes clashing with the inferred harmony, worst severity first