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

    Function analyzeVoice

    • Label every note of a voice with its theory roles.

      Each note is classified against the chord sounding at its beat. Chord tones get a role label; non-chord tones are matched, in order, as suspensions (prepared by an identical consonant pitch and resolving by step), passing tones, neighbors, anticipations, appoggiaturas (approached by leap and resolving by step the other way), and escape tones, then fall back to tension, avoid, or an unresolved-dissonance label. The figures are named as classifyMelodyTones names them, so a caller reading a melody through both layers gets one vocabulary. The two answer different questions and neither refines the other: that classifier weighs the metre, which this one is not given, so it can call ornamental a note this one reads as a chord tone, and the reverse. Leading-tone resolutions are noted additionally, judged against the key in force at the beat the resolution lands on, so a modulation is heard from its new tonic.

      The voice is expected to be monophonic (one note at a time). Notes sharing an onset are treated as simultaneous cluster members, not melodic neighbors, so they receive no melodic labels (suspension, passing, neighbor, anticipation, escape) — only harmonic ones. Callers with truly polyphonic material should split it into monophonic sub-voices first, as analyzeArrangement does.

      Parameters

      • voice: readonly VoiceNote[]

        The monophonic voice, in time order. A note without an id is identified by its position, so plain note events can be passed straight in.

      • chordAtBeat: (beat: number) => ChordData | null

        Chord sounding at a given beat, or null.

      • key: KeyContext

        Key context for leading-tone detection: a single KeyScale covering the whole voice, or a callback giving the key in force at a given beat, for music that modulates.

      • otherVoicesAtBeat: (beat: number) => VoiceSnapshot[] = ...

        Other sounding voices at a given beat; defaults to none, which is the whole story for a solo line.

      Returns AnalyzedNote[]

      One annotation per input note.

      import { analyzeVoice, makeChord, majorKey } from '@libraz/libcantus';
      const voice = [
      { pitch: 60, startBeat: 0, durationBeat: 1 },
      { pitch: 62, startBeat: 1, durationBeat: 1 },
      { pitch: 64, startBeat: 2, durationBeat: 1 },
      ];
      const cMajor = makeChord(0, 'maj');
      const labels = analyzeVoice(voice, () => cMajor, majorKey(0));
      labels; // one AnalyzedNote per input note, in the same order
      // A voice that modulates to C major at beat 2:
      analyzeVoice(voice, () => cMajor, (beat) => (beat < 2 ? majorKey(5) : majorKey(0)));