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

    Class Voicing

    An immutable voicing: the pitches one chord sounds at one moment, lowest voice first (index 0 = the bass), the voice order voiceChord and SATB_RANGES already use.

    The order given is kept rather than sorted: a voicing whose voices are out of order is one whose voices cross, which is a fault Voicing.checkTo reports rather than one the class quietly repairs.

    The voicing, part-writing, counterpoint and safety functions all take the same array of voices; this holds it once and passes it to each of them. Two of the methods read the pitches as a line rather than a chord — Voicing.species and Voicing.independence, which judge a written part slot by slot — and say so.

    The individual counterpoint predicates (createsParallelPerfect, createsVoiceCrossing, and the rest) stay standalone functions: they judge one pair of voices at one moment, which is a question about two pitches rather than about a voicing. Voicing.checkTo is the bundled check.

    import { Voicing } from '@libraz/libcantus';
    Voicing.satb('C').pitches.length; // 4
    Index
    • Wrap a set of sounding pitches.

      Parameters

      • pitches: readonly number[]

        MIDI pitches, lowest voice first; the array is copied, never retained or mutated, and its order is kept. A doubled pitch is kept too, since doubling is how a four-voice texture states a triad.

      Returns Voicing

      If the array is empty, or a pitch is not an integer in 0..127.

    • get pitches(): number[]

      A copy of the sounding MIDI pitches, lowest voice first.

      Returns number[]

    • get range(): VoiceRange

      The compass the voicing occupies: its lowest and highest sounding pitch.

      Read as a VoiceRange so it can be handed straight back as a range for another voice. The pitches are searched rather than read off the ends, so a voicing whose voices cross still reports the compass it sounds.

      Returns VoiceRange

    • Wrap a set of sounding pitches.

      Parameters

      • pitches: readonly number[]

        MIDI pitches, lowest voice first.

      Returns Voicing

      The voicing.

      If the array is empty, or a pitch is not an integer in 0..127.

    • Realize a chord as an explicit tertian voicing in a chosen style — close, drop-2, drop-3, shell or rootless — independent of the SATB range search Voicing.satb runs.

      Parameters

      Returns Voicing

      The voicing, ascending.

      If the voicing would not fit inside MIDI 0..127 at the given octave, or if the style leaves no voice sounding.

      import { Voicing } from '@libraz/libcantus';
      Voicing.forChord('Dm7', { style: 'drop2' }).pitches.length; // 4
    • Realize a chord as one pitch per voice inside the voice ranges, defaulting to the four SATB_RANGES.

      The bass takes the chord's slash bass when it has one, otherwise the root; the result is compact, centred in its ranges, and free of voice crossing.

      A chord that carries a key passes it to the voicer, so the leading tone is not doubled; an explicit opts.key overrides it. That is the order Chord.voice resolves them in, and the two answer alike.

      Parameters

      Returns Voicing

      The voicing, ascending.

      If no voicing fits the given ranges.

      import { Voicing } from '@libraz/libcantus';
      Voicing.satb('Cmaj7').range.min >= 40; // true — the bass stays in its compass
    • Wrap a plain pitch array, as Voicing.data hands it out.

      Parameters

      • data: readonly number[]

        The MIDI pitches.

      Returns Voicing

      The voicing.

      If the array is empty, or a pitch is not an integer in 0..127.

    • Rebuild a voicing from its Voicing.toJSON output.

      Parameters

      • data: readonly number[]

        The serialized pitches.

      Returns Voicing

      The voicing.

      If the array is empty, or a pitch is not an integer in 0..127.

    • Spell the voicing as notes with letters and octaves, so the rules that read letters can be applied to it.

      Each pitch is named against the key, and against the chord sounding under it when one is given, so a chord tone takes the letter its interval above the root implies: the third of a D major chord in C major spells F#, not Gb.

      Parameters

      • key: KeyLike

        A key name, a plain key/scale, or a Key.

      • Optionalchord: ChordLike

        The chord sounding, supplying the enharmonic evidence; without it the key alone decides.

      Returns Note[]

      One spelled note per pitch, in voice order.

      If the value names no key or no chord.

      import { Voicing } from '@libraz/libcantus';
      Voicing.of([50, 57, 66, 69]).spell('C major', 'D').map((note) => note.name);
      // ['D3', 'A3', 'F#4', 'A4']
    • Voice a chord to follow smoothly from this voicing.

      Candidates are enumerated within the ranges opts names, or — when neither voices nor ranges is given — within a one-octave window around each of these pitches, so the answer keeps this voicing's voice count. Each is scored by structural quality, motion from here, and a large penalty per counterpoint violation. A chord that carries a key passes it to the voicer unless opts.key names another one.

      The rules read from the chord being left — a chordal seventh's resolution, a leading tone's resolution, and the cross relation between the two chords — are scored only when opts.previousChord names that chord: a voicing does not say what it was written on.

      Parameters

      • chord: ChordLike

        A chord symbol, plain chord data, or a Chord.

      • Optionalopts: VoicingOptions

        Voicing options; when omitted, the ranges follow this voicing.

      Returns Voicing

      The chosen voicing.

      If this voicing has fewer voices than the requested ranges, or no voicing fits them.

      import { Voicing } from '@libraz/libcantus';
      const tonic = Voicing.satb('C');
      tonic.costTo(tonic.next('G7')) < 24; // true — the voices move economically
    • The voice-leading cost from this voicing to another: the summed absolute semitone motion across voices, and nothing besides. What the motion breaks is Voicing.checkTo's question.

      Parameters

      • other: Voicing

        The voicing moved to.

      Returns number

      The cost, or Infinity when the two hold a different number of voices and are therefore not comparable.

    • Check the motion from this voicing to another against the four-part rules, and report every rule the pair breaks.

      Both voicings are spelled in key against the chord each realizes, then graded as a two-chord exercise: voice crossing, spacing and range inside each chord, and parallel and hidden perfects, overlap, cross relations, augmented melodic intervals and unresolved tendency tones between them.

      Parameters

      • other: Voicing

        The voicing moved to.

      • chords: readonly [ChordLike, ChordLike]

        The chord this voicing realizes and the chord other does.

      • key: KeyLike

        The key the exercise is written in; it names the leading tone.

      • Optionalopts: PartWritingOptions

        Ranges and the upper-voice spacing limit; a four-voice pair is judged against SATB_RANGES when no ranges are given.

      Returns PartWritingViolation[]

      Every violation found, in musical order; an empty array for a clean pair.

      If a value names no chord or key, or the ranges are malformed or too few for the voices being checked.

      import { Voicing } from '@libraz/libcantus';
      const from = Voicing.of([48, 55, 64, 72]);
      const to = Voicing.of([50, 57, 65, 69]);
      from.checkTo(to, ['C', 'Dm'], 'C major').map((found) => found.kind);
      // ['parallelFifth']
    • Mark this voicing, read as a written counterpoint line, against a cantus firmus in one of the five species.

      The pitches are the counterpoint, one per slot rather than one per voice: this is the one place where the array is a line in time instead of a chord in register. Both lines are spelled in mode, since half of what the species rules forbid — the augmented second, the diminished fourth — is invisible in a pitch.

      Parameters

      • cantusFirmus: readonly NoteLike[]

        The given voice, one note per measure, as note names, plain notes, MIDI pitches, or Note instances.

      • species: Species

        Which species the exercise is written in.

      • mode: KeyLike

        The mode the exercise is in.

      • Optionalopts: SpeciesOptions

        Note lengths, and which side the counterpoint is written on; the fifth species cannot be read without durations.

      Returns PartWritingViolation[]

      Every violation found, in the order the exercise commits them.

      If the species is not one of the five, the cantus firmus is empty, or the fifth species is given without durations.

      import { Voicing } from '@libraz/libcantus';
      const counterpoint = Voicing.of([72, 69, 67, 71, 72]);
      counterpoint.species(['C4', 'D4', 'E4', 'D4', 'C4'], 1, 'C major').length; // 0
    • Measure how independent this voicing, read as a line, is from another.

      As in Voicing.species the pitches are slots in time, one per entry, aligned with other slot for slot. Nothing here is a verdict: parallel thirds report as parallel motion with a small separation, a pedal point as oblique motion.

      Parameters

      • other: Voicing

        The line measured against this one, of the same length.

      • Optionalopts: VoicingIndependenceOptions

        Attack flags, the treatment of the fourth, and the key both lines are spelled in.

      Returns VoiceIndependenceReport

      The motion breakdown, rhythmic complementarity, separation, crossings, and the longest perfect-consonance run.

      If the two lines differ in length, or an attack array is supplied at another length than the lines.

    • Judge a candidate pitch placed against these voices.

      Every pitch of this voicing stands as another part sounding under the candidate, so the vertical rules read them all; the motion rules need query.previous, which gives each of those voices the pitch it came from.

      Parameters

      • pitch: number

        The candidate MIDI pitch.

      • query: VoicingSafetyQuery

        The candidate's harmonic and voice-leading context.

      • Optionalopts: EvaluateSafetyOptions

        Set suggestions: false to skip the search for safe replacements when the verdict is not safe.

      Returns SafetyResult

      The verdict, reason bitmask, and optional resolution guidance.

      If the profile is unknown, a value names no chord or key, or a pitch is not a MIDI pitch in 0..127.

      import { NoteSafety } from '@libraz/libcantus';
      import { Voicing } from '@libraz/libcantus';
      const sounding = Voicing.of([48, 55, 64]);
      sounding.safetyOf(72, { profile: 'pop', chord: 'C', key: 'C major', strongBeat: true })
      .safety === NoteSafety.Safe; // true
    • Enumerate the pitches placeable against these voices in a range, chord tones first, each group descending.

      Parameters

      • query: VoicingSafetyQuery

        The harmonic and voice-leading context, as Voicing.safetyOf reads it.

      • pitchLow: number

        Lowest MIDI pitch to consider (inclusive).

      • pitchHigh: number

        Highest MIDI pitch to consider (inclusive).

      Returns number[]

      The placeable pitches — those not judged dissonant.

      If the profile is unknown, a value names no chord or key, or a bound is not a MIDI pitch in 0..127 or is reversed.

    • The n-th inversion of the voicing: the lowest voice taken up an octave, n times over.

      A negative n takes the highest voice down an octave as many times, and invert(0) is the voicing itself, voice order and all. Unlike Chord.invert, which rotates a chord's interval template, this moves real voices: inverting a four-voice texture four times leaves the same chord an octave higher. A voicing that actually inverts comes back ascending, since the voice that moved is no longer where it was.

      Parameters

      • n: number

        How many voices to move, upward when positive.

      Returns Voicing

      The inverted voicing, ascending; this voicing itself when n is 0.

      If n is not an integer in [-128, 128], or a voice would leave MIDI 0..127.

      import { Voicing } from '@libraz/libcantus';
      Voicing.of([60, 64, 67]).invert(1).pitches; // [64, 67, 72]
    • Whether another voicing sounds the same pitches in the same order.

      A doubling counts: two voices on the same pitch are two voices, and a three-voice texture is not the four-voice one that doubles its root.

      Parameters

      • other: Voicing

        The voicing to compare.

      Returns boolean

      True when the pitches match one for one.

    • The plain pitch array, for JSON serialization.

      Private class fields do not serialize, so an explicit toJSON keeps JSON.stringify(voicing) from collapsing to {}.

      Returns VoicingData

      A copy of the sounding MIDI pitches, in voice order.

    • The pitches separated by spaces, so a template literal or a log line reads as the voicing.

      Returns string

      The pitches in voice order, e.g. '60 64 67'.