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

    Function harmonizeMelody

    • Harmonize a melody with a min-cost chord progression.

      The melody's ornaments are classified first, from the melody and the metre alone (see classifyMelodyTones); the chords then have to explain the structural tones only, so a passing tone no longer buys itself a chord. The melody is segmented by harmonicRhythm; each segment is scored against the candidate chords the harmonic dial opens — the key's own triads, then the secondary dominants, then the parallel mode's chords, one at a time as ctx.complexity.harmonic rises from 0 to 1 — by the fit of those structural tones, and a Viterbi search picks the lowest-cost path using a functional-flow transition cost and a cadence bonus at the end of the melody it is given — one cadence, at the close, unless phraseEnds names the closes inside a longer line, and then one at each of them as well. Runs of the same chord are reported once, so the chord count follows the harmony rather than the grid.

      With placement.transposeSearch the melody is moved into the key it is harmonized in, and transposeSemitones reports how far; with placement.octaveSearch it is moved by octaves into a comfortable register, which leaves the key and the chords untouched. Both may be set, and the reported shift is their sum.

      The seed drives a deterministic tie-break only: it perturbs candidates by a magnitude far below any real cost difference (see TIE_BREAK_JITTER), so it can decide between chords or paths of otherwise-equal cost but never overrides melody fit or functional flow. For a well-determined melody the result is identical across seeds; the same seed always yields the same result.

      Parameters

      • opts: HarmonizeOptions

        The melody and, optionally, the generation context, key, harmonic rhythm, reharmonization strength, placement search, meter, and seed. Only melody is required.

      Returns HarmonizeResult

      The chosen transpose, key, chord path, and per-note roles.

      import { harmonizeMelody } from '@libraz/libcantus';
      const result = harmonizeMelody({
      melody: [
      { pitch: 60, startBeat: 0, durationBeat: 1 },
      { pitch: 64, startBeat: 1, durationBeat: 1 },
      ],
      });
      result.chords; // one ChordSpan per chord change, on the harmonic-rhythm grid