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

    Class Timeline

    Harmony that keeps its place in time: chord segments over a span of beats, with the key regions the analysis found under them.

    This is the timed counterpart of Progression, which holds an ordered list of chords and deliberately drops their onsets. A piece read from a MIDI track has both a chord order and a chord rhythm, and until now only the order could be held in a class; Timeline is where the rhythm lives.

    import { Chord, Key, Progression, Timeline } from '@libraz/libcantus';
    const timeline = Timeline.fromProgression(
    new Progression([Chord.parse('C'), Chord.parse('G7')], Key.major('C')),
    4,
    );
    timeline.at(5)?.symbol(); // 'G7'
    timeline.roman().map((entry) => entry.roman); // ['I', 'V7']
    Index
    • Wrap plain timeline data.

      Parameters

      • data: TimelineData

        The segments and the span they cover; copied, never retained.

      Returns Timeline

      If the span, a segment, or a key region carries a number it cannot hold — a beat that is not finite, a mode mask that names no scale — or if the confidences do not run one per segment.

    • get key(): Key | undefined

      The key held longest across the span, when the analysis found one.

      Returns Key | undefined

    • get segmentConfidence(): readonly number[]

      How sure the analysis is of each segment's chord, in [0, 1] and in segment order, so a reading is paired with the segment it describes by position.

      A confidence answers the question a chord symbol cannot: whether the notes really spell that chord, or whether a passing figure was the best of a bad set of candidates. Empty on a timeline whose chords were placed rather than inferred — Timeline.fromChords and Timeline.fromProgression are given the harmony, so there is no reading to report.

      Returns readonly number[]

      import { Timeline } from '@libraz/libcantus';
      const timeline = Timeline.fromNotes([
      { pitch: 60, startBeat: 0, durationBeat: 4 },
      { pitch: 64, startBeat: 0, durationBeat: 4 },
      { pitch: 67, startBeat: 0, durationBeat: 4 },
      ]);
      timeline.segmentConfidence.length === timeline.length; // true
    • Build a timeline from placed chords.

      Parameters

      • spans: readonly ChordSpan[]

        The chords with their onsets, in any order.

      • totalBeats: number

        Where the last chord stops sounding.

      • Optionalkey: KeyLike

        The key the chords are read in, when it is already known. It becomes the one key region under the whole span; without it the timeline carries no key, and the members that need one say so.

      Returns Timeline

      The timeline.

    • Place a progression's chords on a regular grid.

      The chords cross over as harmony alone: a spelling one of them carried is dropped, since a chord placed on the grid is a ChordSpan and a span carries none. A carried key becomes the one key region under the span, spelled tonic and scale form included — an Ab minor comes back Ab minor, which is what the numerals over the region are read from.

      Parameters

      • progression: Progression

        The chords, in order.

      • beatsEach: number

        How long each chord sounds.

      Returns Timeline

      The timeline.

      If beatsEach is not a positive finite number of beats.

    • The chord sounding at a beat, or null where nothing is.

      A segment covers [startBeat, endBeat), so the beat a chord gives way on answers with the chord arriving rather than the one leaving. The chord carries the key in force at that beat when the timeline knows one, so it can name its own numeral and function.

      Parameters

      • beat: number

        The beat to read.

      Returns Chord | null

      The chord, or null outside every segment.

      If beat is not finite.

    • Drop the time axis, keeping the chord order.

      Explicit rather than implicit, because the onsets are information and losing them silently is how a chord rhythm disappears from a pipeline. A rest between two segments goes with them: the chords either side become neighbours in the progression.

      Returns Progression

      The chords in order, carrying the prevailing key when there is one.

    • The cadences the harmony arrives at.

      Each hit carries the beat it arrives on as well as the cadence itself: a cadence without its onset says that the music cadenced but not where, which is the one thing a timed class is holding that a chord pair is not.

      Returns CadenceHit[]

      The cadences found, in time order.

      If the timeline carries no key region to read the chords against.

    • The keys the chords themselves imply, in time order.

      The chord route to key regions, for a timeline that holds harmony without the notes it was played from — a lead sheet, or a progression laid out in time. A chord argues for a key far more strongly than its three or four pitch classes do, so a modulation is read off the chords rather than off a pitch-class profile, and the chord that reads in both keys is reported as the pivot the modulation turned on.

      The regions are searched for here rather than kept on the timeline: Timeline.keys answers with what the timeline was built with, which for placed chords is the key the caller stated or nothing at all.

      Parameters

      Returns KeyRegion[]

      The key regions the chords imply; empty when there are no chords.

      import { Chord, Key, Progression, Timeline } from '@libraz/libcantus';
      const progression = new Progression(
      [Chord.parse('C'), Chord.parse('G7'), Chord.parse('C')],
      Key.major('C'),
      );
      Timeline.fromProgression(progression, 4).modulations().length; // 1
    • The stretch of the timeline between two beats.

      Beats are kept as they are rather than rebased on the slice, so a sliced timeline still lines up with the score it was read from; totalBeats becomes where the slice ends. A segment or key region straddling an edge is clipped to it, and one reduced to nothing is dropped.

      Parameters

      • fromBeat: number

        First beat of the stretch.

      • toBeat: number

        End of the stretch, exclusive.

      Returns Timeline

      The clipped timeline.

      If either beat is not finite, or toBeat precedes fromBeat.

    • The timeline moved by a number of semitones.

      The key regions move with the chords, so every segment keeps the degree and function it had in the key it sounded in.

      Parameters

      • semitones: number

        The signed semitone offset.

      Returns Timeline

      The transposed timeline.

    • The timeline moved by a spelled interval, keeping the spelling.

      Unlike Timeline.transpose, which picks letters from a semitone count, the interval's diatonic number decides them: a chord taken up an augmented fourth is spelled with sharps and one taken up a diminished fifth with flats.

      Only a chord carrying a spelling of its own is spelled that way. A key region holds a key/scale rather than a spelled key, so a chord that takes its letters from the key in force follows the spelling that scale reads best from, whichever interval moved it there.

      Parameters

      • interval: IntervalLike

        An interval name (e.g. 'A4', '-m3'), plain interval data, or an Interval; a descending interval moves down.

      Returns Timeline

      The transposed timeline.

    • Whether another timeline holds the same chords over the same span.

      The key regions are not compared: they are an analysis lens over the chords, the way a Progression's key context is over its own.

      Parameters

      • other: Timeline

        The timeline to compare.

      Returns boolean

      True when the segments and the span both match.