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

    Function spellLine

    • 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:

      1. A note the sounding chord names takes that chord's spelling of it, even when the key spells the pitch otherwise — the seventh of a Db7 reads Cb in C major, not B.
      2. Anything else the key's scale spells keeps its key spelling, exactly as the note-by-note path keeps it.
      3. A chromatic note is spelled so the written intervals around it match the sounding ones, and then so a rising step carries a sharp and a falling step a flat.
      4. Failing all of that, the key's own chromatic spelling stands, and the fewest accidentals win.

      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.

      Parameters

      • notes: readonly NoteEvent[]

        The line, monophonic and in time order. Notes sharing an onset are read as consecutive, so split polyphonic material into voices first.

      • timeline: ChordTimeline | null

        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.

      • key: SpelledKeyLike

        The key the line is written in, as a key name, a key/scale, or a Key.

      • opts: SpellLineOptions = {}

        Optional tonic spelling and work budget.

      Returns NoteData[]

      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']