The cell, in time order. Notes that never sound are dropped, and notes sharing an onset are folded to their top voice.
The motif, carrying exactly one occurrence.
import { motifFromNotes, relateMotifs } from '@libraz/libcantus';
const subject = motifFromNotes([
{ pitch: 60, startBeat: 0, durationBeat: 1 },
{ pitch: 62, startBeat: 1, durationBeat: 1 },
{ pitch: 64, startBeat: 2, durationBeat: 1 },
]);
const answer = motifFromNotes([
{ pitch: 67, startBeat: 3, durationBeat: 1 },
{ pitch: 69, startBeat: 4, durationBeat: 1 },
{ pitch: 71, startBeat: 5, durationBeat: 1 },
]);
relateMotifs(subject, answer)?.kind; // 'transposition'
Read a run of notes as a single-statement motif.
extractMotifs answers with motifs it found recurring; this is how a caller names one it already has — a subject, an answer, a phrase lifted out of a score — so that it can be handed to relateMotifs.
The cell is expected to be monophonic, as analyzeVoice expects a voice to be. Notes struck together are read as one event, the highest of them standing for it, so a chord is reduced to its top voice rather than read as a line of its own.