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

    Function generateMelody

    • Write a melody that follows a composition plan.

      Each phrase is written inside its planned register, and every note the generator chooses freely takes a pitch its position class admits: a chord tone on a strong pulse, a scale tone on a weak one, any pitch off the pulses. A root motif takes the onset gaps its plan carries from its start, its last note lasting to its end, or onsets drawn one after another on the sixteenth grid toward the plan's onset levels and gap shares; its pitches come from a chain search that moves by step, recovers from leaps and follows the phrase's target shape. A derived motif replays its planned relation on the statement it derives from, starting on its planned beat, at the pitch level inside the register that best fits the harmony, the target curve and the planned level; a harmony misfit it keeps is left, and only notes no level brings inside the register are replaced. A variation keeps its source's rhythm and outer pitches. The spans no motif covers get drawn onsets at the phrase's density and searched pitches. In each phrase's final bar, the note sounding at the downbeat (or the first onset after it) is held to the phrase's end, later onsets are dropped, and that note is bent onto the tones the phrase's cadence asks for; a note sounding across the downbeat is cut there, and the downbeat becomes the held onset, re-chosen from the pitches the downbeat admits unless a cadence or a derived statement decides it. Onsets fall on the sixteenth grid only, so triplets never appear.

      Harmony is read from the plan alone, through planTimeline.

      Parameters

      Returns NoteEvent[]

      The melody, in time order.

      If the plan, the options or the context are malformed, or the context supplies an rng.

      If a phrase's register admits no line, no pitch a position asks for, no pitch that ends its cadence, or a span more onsets than its grid holds; at is the phrase's start beat.

      If the onset grid or the pitch search would exceed the budget.

      import { generateMelody, resolveKey } from '@libraz/libcantus';
      import type { CompositionPlan } from '@libraz/libcantus';
      const plan: CompositionPlan = {
      planVersion: 1, seed: 7, algorithmVersion: 1,
      keys: [resolveKey('C major')], meters: [{ startBeat: 0, ts: { numerator: 4, denominator: 4 } }],
      span: { startBeat: 0, endBeat: 8, bars: 2 },
      sections: [{ label: 'A', startBeat: 0, endBeat: 8 }],
      phrases: [{
      startBeat: 0, endBeat: 8, section: 0, cadence: 'authentic', shape: 'arch', peakPosition: 0.6,
      register: { low: 60, high: 72, mean: 66 }, onsetDensity: 4, motifs: [0],
      }],
      harmony: [{ startBeat: 0, endBeat: 4, key: 0, roman: 'V' }, { startBeat: 4, endBeat: 8, key: 0, roman: 'I' }],
      motifs: [{ phrase: 0, startBeat: 0, endBeat: 4, notes: 4, rhythm: [1, 1, 1], from: null, relation: null }],
      rhythm: { onsetLevels: [0, 0, 0, 0, 0, 1], interOnsetShares: new Array(17).fill(0).fill(1, 8, 9), syncopation: 0 },
      };
      generateMelody(plan); // the same notes on every call