The chord timeline the cadences are read from.
The melody, for its rests, held notes and repetitions. Notes that never sound are dropped.
Analysis options; see PhraseOptions.
The phrases, in time order; one phrase covering the whole span when the span is too short to divide, and none at all when nothing sounds — silence is no material to hear a phrase in.
import { chordTimelineFromNotes, phrasesFromTimeline } from '@libraz/libcantus';
// Four bars of C - F - G - C. Triads rather than single notes: one line at a
// time names no harmony, so nothing would cadence.
const triad = (pitches: number[], startBeat: number) =>
pitches.map((pitch) => ({ pitch, startBeat, durationBeat: 4 }));
const notes = [
...triad([60, 64, 67], 0),
...triad([65, 69, 72], 4),
...triad([67, 71, 74], 8),
...triad([60, 64, 67], 12),
];
const { timeline } = chordTimelineFromNotes(notes);
const phrases = phrasesFromTimeline(timeline, notes);
phrases[phrases.length - 1]?.cadence?.cadence.type; // 'authentic'
phrases[phrases.length - 1]?.cadence?.atBeat; // 12, inside the phrase it closes
Split a piece into phrases.
Three kinds of evidence are gathered independently and then reconciled. The harmony contributes its cadences, each closing at the end of the chord it arrives on, and at the bar line where that chord is held across one — a tonic still sounding into the next phrase closed this one at the bar line. The cadence reported for a phrase is always one that arrived inside it. The melody contributes the rests it breathes at and the notes it holds long enough to read as arrivals. Repetition contributes the beats where the music restarts material it has just played. The metre contributes its hypermetric downbeats, which confirm a boundary but never declare one on their own.
The boundaries are then chosen together rather than one at a time: the reading that best trades each boundary's evidence against how regular the phrase lengths come out is selected by dynamic programming, at a fixed cost per cut. That is what stops a phrase being declared at every plausible beat, and what lets a well-evidenced irregular phrase survive next to regular ones.
The result is contiguous: phrases abut, and together they cover the span from the first note to the end of the music. A cadence found in the middle of a phrase is not lost — it is still reachable through detectCadences — but only the cadences the reading puts at phrase ends are ranked by structuralCadences.