The line, monophonic and in time order. Notes sharing an onset are read as consecutive, so split polyphonic material into voices first.
The chords sounding under the line, or null when only the key is known. Each note is judged against the chord at its own onset.
The key the line is written in, as a key name, a key/scale, or a
Key.
Optional tonic spelling and work budget.
One spelled note per input note, in input order, each carrying the octave that reproduces its pitch.
If opts.tonic does not sound the key's root pitch class, if a note
event is malformed, or if the line is longer than the budget allows.
import { chordTimelineFromChords, majorKey, noteNames, spellLine } from '@libraz/libcantus';
// A chromatic ascent spells with sharps, whatever the key would say alone.
const rising = [60, 61, 62, 63, 64].map((pitch, index) => ({
pitch,
startBeat: index,
durationBeat: 1,
}));
noteNames(spellLine(rising, null, majorKey(0)));
// ['C4', 'C#4', 'D4', 'D#4', 'E4']
// Under a Db7 the same B sounds as the chord's seventh.
const timeline = chordTimelineFromChords([{ rootPc: 1, quality: 'dom7', startBeat: 0 }], 4);
noteNames(spellLine([{ pitch: 71, startBeat: 0, durationBeat: 1 }], timeline, majorKey(0)));
// ['Cb5']
Spell a whole melodic line at once, so its notes agree with each other.
Every note is spelled together with the rest of the line rather than one at a time: each pitch offers the three spellings a double accidental allows, the chord and the key price them, the intervals between neighbours price the pairs, and the cheapest reading of the whole line wins. Ties fall to the spelling spellPitchClass would have chosen alone, so the answer never drifts from the theory layer without a reason.
Four rules decide, in this order:
Without a timeline — pass
null— rules 2 to 4 still apply in full, so a diatonic line and a chromatic run come out the same. What is lost is rule 1: a chromatic chord can no longer name its own tones, so the tones of a borrowed or altered chord fall back to the key's convention (that Cb becomes B), and an enharmonically ambiguous tone under a chord that would have fixed it is decided by the line's direction instead.