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

    Function detectModulations

    • Infer where the key changes from a chord sequence, naming the pivot chords.

      Each chord segment is one slot of the same search keyTimelineFromNotes runs, scored by how well the chord belongs to each key rather than by a pitch-class profile — a dominant seventh argues for its key far more strongly than its three or four pitch classes alone would suggest. Where the key changes, the chord sounding into the boundary is reported as the pivot if it reads in both keys.

      The chords supply the slots, so minKeyBeats cannot size them as it does in the note path; a region shorter than it is folded into the neighbouring key that reads its chords best instead, which is the same guarantee — a shorter region is reported only where the analyzed span itself ends, or across a gap in the chords that no neighbour adjoins. profile scores each region's confidence, as it does in the note path, but takes no part in choosing which keys are reported: that is settled by how the chords read.

      A region's evidence is the run of segments it was grouped from, which is the same reading the search itself makes of them. Where the segments given overlap each other — a chart is a sequence, so a chord timeline's are not — a chord held past the segment after it argues for its own segment's key rather than for both.

      Parameters

      Returns KeyRegion[]

      The key regions in time order; empty when no chords were given.

      import { chordTimelineFromNotes, detectModulations } from '@libraz/libcantus';
      const notes = [
      { pitch: 60, startBeat: 0, durationBeat: 4 },
      { pitch: 64, startBeat: 0, durationBeat: 4 },
      { pitch: 67, startBeat: 0, durationBeat: 4 },
      ];
      const { timeline } = chordTimelineFromNotes(notes);
      const regions = detectModulations(timeline.segments);