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

    Function generateCounterMelody

    • Generate a counter melody against a lead line.

      Onsets are chosen per rhythm: 'follow' places one counter note on each melody onset; 'complement' fills melody rests and sustains and reinforces an occasional strong beat, spaced at least a beat apart. Each onset's pitch is picked from the safe pitches in the counter register (chord tones and consonant tensions against the sounding melody note), rejecting candidates that would form a parallel perfect interval with the melody or sit on the wrong side of it, then ranked by the profile's weights — which is where the two styles part company: 'strict' prefers contrary motion and penalizes similar, 'pop' rewards a run of parallel thirds or sixths and is content with a pedal. Ties are broken by a seeded perturbation far below any real score difference (see TIE_BREAK_JITTER), so the same seed always yields the same line while a different seed can only reshuffle candidates that were already equally good. Notes extend to the next counter onset (the last to the melody's end) at a velocity slightly under the melody.

      Parameters

      Returns NoteEvent[]

      The counter line as note events sorted by onset; [] for an empty melody.

      If an option names a value outside its range — including a weight override that is not a finite number, which is rejected before any candidate is scored rather than absorbed into the ranking.

      import { generateCounterMelody, majorKey, parseChordSymbol } from '@libraz/libcantus';
      const melody = [{ pitch: 72, startBeat: 0, durationBeat: 2 }];
      const counter = generateCounterMelody({
      melody,
      chordAt: () => parseChordSymbol('C'),
      key: majorKey(0),
      }); // note events below the melody, in onset order