@libraz/libcantus 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -65
- package/README_ja.md +28 -66
- package/dist/analyze/index.cjs +11 -7
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +79 -144
- package/dist/analyze/index.d.ts +79 -144
- package/dist/analyze/index.js +20 -16
- package/dist/chunk-35NBV2FT.cjs +145 -0
- package/dist/chunk-35NBV2FT.cjs.map +1 -0
- package/dist/{chunk-UADYAYAT.cjs → chunk-3R3QVKY5.cjs} +1353 -580
- package/dist/chunk-3R3QVKY5.cjs.map +1 -0
- package/dist/{chunk-WWURE4XT.cjs → chunk-76ZBTRG2.cjs} +624 -729
- package/dist/chunk-76ZBTRG2.cjs.map +1 -0
- package/dist/{chunk-FVSI36UV.js → chunk-7KG3RTYS.js} +197 -110
- package/dist/chunk-7KG3RTYS.js.map +1 -0
- package/dist/{chunk-VTI6FOLB.js → chunk-AGOVW7U6.js} +709 -133
- package/dist/chunk-AGOVW7U6.js.map +1 -0
- package/dist/{chunk-E3F4AHAH.cjs → chunk-CGBADIO5.cjs} +221 -134
- package/dist/chunk-CGBADIO5.cjs.map +1 -0
- package/dist/{chunk-6XH6QZYQ.cjs → chunk-DSMJRXCZ.cjs} +1455 -849
- package/dist/chunk-DSMJRXCZ.cjs.map +1 -0
- package/dist/{chunk-PKFNUHDY.js → chunk-FBH75DAY.js} +1218 -612
- package/dist/chunk-FBH75DAY.js.map +1 -0
- package/dist/chunk-H2KJHBW4.js +3329 -0
- package/dist/chunk-H2KJHBW4.js.map +1 -0
- package/dist/chunk-HPVSH7SF.cjs +2294 -0
- package/dist/chunk-HPVSH7SF.cjs.map +1 -0
- package/dist/{chunk-MXO72PLY.cjs → chunk-HWHGOVO6.cjs} +21 -19
- package/dist/chunk-HWHGOVO6.cjs.map +1 -0
- package/dist/chunk-HYJJ2V2I.js +2294 -0
- package/dist/chunk-HYJJ2V2I.js.map +1 -0
- package/dist/{chunk-AFM2ULJH.cjs → chunk-J7FHVZII.cjs} +1567 -1067
- package/dist/chunk-J7FHVZII.cjs.map +1 -0
- package/dist/chunk-K6OZXIR6.js +1 -0
- package/dist/{chunk-H3VORETI.js → chunk-M5RYMAFI.js} +487 -592
- package/dist/chunk-M5RYMAFI.js.map +1 -0
- package/dist/chunk-NB25P3EH.js +363 -0
- package/dist/chunk-NB25P3EH.js.map +1 -0
- package/dist/{chunk-TTCLJX6D.js → chunk-NFJ4P6ZZ.js} +10 -8
- package/dist/chunk-NFJ4P6ZZ.js.map +1 -0
- package/dist/chunk-NM7UAMC3.cjs +457 -0
- package/dist/chunk-NM7UAMC3.cjs.map +1 -0
- package/dist/chunk-PM4XJE2Y.cjs +363 -0
- package/dist/chunk-PM4XJE2Y.cjs.map +1 -0
- package/dist/chunk-PUKJP2Z5.js +145 -0
- package/dist/chunk-PUKJP2Z5.js.map +1 -0
- package/dist/{chunk-VOHZB45S.js → chunk-Q6LFSAKV.js} +1321 -821
- package/dist/chunk-Q6LFSAKV.js.map +1 -0
- package/dist/{chunk-INHVXP6Z.js → chunk-RFIBF2RR.js} +1203 -430
- package/dist/chunk-RFIBF2RR.js.map +1 -0
- package/dist/{chunk-Q2WGKJNN.cjs → chunk-S5BKZZGM.cjs} +699 -123
- package/dist/chunk-S5BKZZGM.cjs.map +1 -0
- package/dist/chunk-SGLEQVJH.cjs +3329 -0
- package/dist/chunk-SGLEQVJH.cjs.map +1 -0
- package/dist/chunk-UGLFDG7L.cjs +1 -0
- package/dist/chunk-UGLFDG7L.cjs.map +1 -0
- package/dist/{chunk-YH3BIKHH.js → chunk-UMWZ4ZET.js} +146 -49
- package/dist/chunk-UMWZ4ZET.js.map +1 -0
- package/dist/{index-szBv3496.d.ts → coerce-DP0vYu-x.d.ts} +286 -199
- package/dist/{index-C_8o--VE.d.cts → coerce-DRERzdve.d.cts} +286 -199
- package/dist/core/index.cjs +9 -5
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +122 -108
- package/dist/core/index.d.ts +122 -108
- package/dist/core/index.js +32 -28
- package/dist/generate/index.cjs +8 -8
- package/dist/generate/index.d.cts +168 -84
- package/dist/generate/index.d.ts +168 -84
- package/dist/generate/index.js +7 -7
- package/dist/{index-CGpRv5sl.d.cts → index-9eoQs2C1.d.ts} +34 -19
- package/dist/{index-CCNJRG-P.d.cts → index-B9QLziDe.d.cts} +293 -56
- package/dist/{index-Dzr13q3d.d.cts → index-BBWNZS0f.d.cts} +135 -58
- package/dist/{index-9wcMhG73.d.ts → index-BHIUyjhZ.d.ts} +293 -56
- package/dist/{index-BGFW-8P2.d.cts → index-BJgP97N1.d.ts} +196 -114
- package/dist/{index-CunYKLiu.d.ts → index-BL5N2Oyz.d.cts} +1 -1
- package/dist/{index-Cj49F892.d.ts → index-BMweUlm5.d.cts} +63 -23
- package/dist/{index-CgHqxdps.d.ts → index-BNSM-DSk.d.cts} +196 -114
- package/dist/{index-D57QRbVn.d.ts → index-BRMbPkHE.d.ts} +480 -254
- package/dist/{index-Chbst3Jx.d.ts → index-CJBBiAmU.d.ts} +135 -58
- package/dist/{index-BkGmlyI3.d.cts → index-CL4b4gUQ.d.ts} +63 -23
- package/dist/{index-B9MNZboQ.d.ts → index-Cy15oTvh.d.cts} +52 -22
- package/dist/{index-B9MNZboQ.d.cts → index-Cy15oTvh.d.ts} +52 -22
- package/dist/{index-BO6xE9YU.d.cts → index-DGCNKAUr.d.cts} +480 -254
- package/dist/{index-B4o55NDr.d.cts → index-Dw2DP7vm.d.ts} +1 -1
- package/dist/{index-G1uwGGWQ.d.ts → index-cHvbYgJI.d.cts} +34 -19
- package/dist/index.cjs +42 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -14
- package/dist/index.d.ts +14 -14
- package/dist/index.js +82 -54
- package/dist/{masks-DYbE485J.d.cts → masks-Cc7-MzzY.d.ts} +49 -2
- package/dist/{masks-DYbE485J.d.ts → masks-pADfTOiD.d.cts} +49 -2
- package/dist/model/index.cjs +19 -12
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +504 -182
- package/dist/model/index.d.ts +504 -182
- package/dist/model/index.js +18 -11
- package/dist/{positional-Cptlj-xs.d.ts → positional-DJgs6ltD.d.ts} +85 -8
- package/dist/{positional-DvH_sd8u.d.cts → positional-DMZer-FM.d.cts} +85 -8
- package/dist/theory/index.cjs +35 -6
- package/dist/theory/index.cjs.map +1 -1
- package/dist/theory/index.d.cts +257 -62
- package/dist/theory/index.d.ts +257 -62
- package/dist/theory/index.js +41 -12
- package/package.json +7 -5
- package/dist/chunk-2LCPM3EG.js +0 -3224
- package/dist/chunk-2LCPM3EG.js.map +0 -1
- package/dist/chunk-6XH6QZYQ.cjs.map +0 -1
- package/dist/chunk-6XPTBE7Y.cjs +0 -49
- package/dist/chunk-6XPTBE7Y.cjs.map +0 -1
- package/dist/chunk-AFM2ULJH.cjs.map +0 -1
- package/dist/chunk-B6XNKWZV.cjs +0 -3224
- package/dist/chunk-B6XNKWZV.cjs.map +0 -1
- package/dist/chunk-E3F4AHAH.cjs.map +0 -1
- package/dist/chunk-ELCTZUJJ.js +0 -379
- package/dist/chunk-ELCTZUJJ.js.map +0 -1
- package/dist/chunk-FVSI36UV.js.map +0 -1
- package/dist/chunk-H3VORETI.js.map +0 -1
- package/dist/chunk-H42UHPYW.js +0 -1577
- package/dist/chunk-H42UHPYW.js.map +0 -1
- package/dist/chunk-HFPS7JFD.js +0 -1
- package/dist/chunk-INHVXP6Z.js.map +0 -1
- package/dist/chunk-K4ZJUGF4.cjs +0 -379
- package/dist/chunk-K4ZJUGF4.cjs.map +0 -1
- package/dist/chunk-KNJEKLKV.js +0 -49
- package/dist/chunk-KNJEKLKV.js.map +0 -1
- package/dist/chunk-MXO72PLY.cjs.map +0 -1
- package/dist/chunk-NLEU4QSE.cjs +0 -360
- package/dist/chunk-NLEU4QSE.cjs.map +0 -1
- package/dist/chunk-OE6WK2Y2.cjs +0 -1577
- package/dist/chunk-OE6WK2Y2.cjs.map +0 -1
- package/dist/chunk-PKFNUHDY.js.map +0 -1
- package/dist/chunk-Q2WGKJNN.cjs.map +0 -1
- package/dist/chunk-RHIJ3S4I.cjs +0 -1
- package/dist/chunk-RHIJ3S4I.cjs.map +0 -1
- package/dist/chunk-TTCLJX6D.js.map +0 -1
- package/dist/chunk-UADYAYAT.cjs.map +0 -1
- package/dist/chunk-VOHZB45S.js.map +0 -1
- package/dist/chunk-VTI6FOLB.js.map +0 -1
- package/dist/chunk-WWURE4XT.cjs.map +0 -1
- package/dist/chunk-YH3BIKHH.js.map +0 -1
- /package/dist/{chunk-HFPS7JFD.js.map → chunk-K6OZXIR6.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/model/interval.ts","../src/model/shared.ts","../src/model/note.ts","../src/model/timeline.ts","../src/model/progression.ts","../src/model/chord.ts","../src/model/key.ts","../src/model/score.ts","../src/model/arrangement.ts","../src/model/instrument.ts","../src/model/composer.ts","../src/model/duration.ts","../src/model/meter.ts","../src/model/motif.ts","../src/model/rhythm.ts","../src/model/tempo.ts","../src/model/tuning.ts","../src/model/voicing.ts"],"sourcesContent":["import { type ParseResult, unwrapParse } from '../core/errors/index.js';\nimport { isConsonantInterval } from '../core/interval/index.js';\nimport type { IntervalData, IntervalQualityLabel, SpelledInterval } from '../core/pitch/index.js';\nimport { intervalSemitones, toSpelledInterval, tryParseInterval } from '../core/pitch/index.js';\nimport type { Note } from './note.js';\n\n/** Number of diatonic degrees an interval and its inversion span together. */\nconst INVERSION_SUM = 9;\n\n/** Diatonic size of an octave, the largest simple interval. */\nconst OCTAVE_DEGREES = 8;\n\n/**\n * The simple interval a diatonic number belongs to.\n *\n * Seven is subtracted while the number is larger than an octave, so the octave\n * and its multiples (8, 15, 22, ...) reduce to the octave rather than to the\n * unison: plain modulo-7 arithmetic folds them onto 1 and would then invert a\n * double octave as if it were a unison.\n */\nfunction simpleDegree(numberValue: number): number {\n const reduced = ((numberValue - 1) % 7) + 1;\n return reduced === 1 && numberValue > 1 ? OCTAVE_DEGREES : reduced;\n}\n\n/** The quality an interval's inversion carries. */\nfunction invertQuality(quality: IntervalQualityLabel): IntervalQualityLabel {\n if (quality === 'P') {\n return 'P';\n }\n if (quality === 'M') {\n return 'm';\n }\n if (quality === 'm') {\n return 'M';\n }\n return quality.startsWith('A')\n ? (`d${'d'.repeat(quality.length - 1)}` as IntervalQualityLabel)\n : (`A${'A'.repeat(quality.length - 1)}` as IntervalQualityLabel);\n}\n\n/**\n * An immutable spelled interval value: a diatonic number, a quality label, and\n * a signed semitone span. A thin convenience wrapper over the pitch module's\n * plain interval result.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Interval, Note } from '@libraz/libcantus';\n * Interval.between(Note.parse('C4'), Note.parse('G4')).name; // 'P5'\n * ```\n */\nexport class Interval {\n readonly #number: number;\n readonly #quality: IntervalQualityLabel;\n readonly #semitones: number;\n readonly #descending: boolean;\n\n private constructor(\n numberValue: number,\n quality: IntervalQualityLabel,\n semitones: number,\n descending = semitones < 0,\n ) {\n this.#number = numberValue;\n this.#quality = quality;\n this.#semitones = semitones;\n this.#descending = descending;\n }\n\n /**\n * The spelled interval between two notes.\n *\n * @param a The first note.\n * @param b The second note.\n * @returns The interval from `a` to `b`.\n */\n static between(a: Note, b: Note): Interval {\n return a.intervalTo(b);\n }\n\n /**\n * Build an interval from explicit components.\n *\n * @param numberValue Diatonic size: 1 = unison, 2 = second, ... 8 = octave.\n * @param quality Quality label: `'P'`, `'M'`, `'m'`, or repeated `'A'`/`'d'`.\n * @param semitones Signed semitone span; its magnitude must be the span the\n * number and quality describe.\n * @returns The interval.\n * @throws If the three components do not describe the same interval — a\n * `P5` spanning 8 semitones is not a value any other method can produce.\n */\n static of(numberValue: number, quality: IntervalQualityLabel, semitones: number): Interval {\n return Interval.fromData({ number: numberValue, quality, semitones });\n }\n\n /**\n * Wrap a plain spelled interval, as returned by the pitch module.\n *\n * The data is checked the way {@link Interval.of} checks its arguments: a\n * deserialized interval enters through here, and an unchecked one would be a\n * value no measurement produces — a `P5` spanning eight semitones names\n * itself a fifth while sounding a sixth.\n *\n * @param data The plain interval.\n * @returns The wrapped interval.\n * @throws If the number, quality, and span do not describe the same interval.\n */\n static fromData(data: IntervalData): Interval {\n // The direction is read off the canonical data rather than from the span's\n // sign: an interval can climb a letter while losing a semitone — C# up to\n // Dbb is a doubly diminished second — and only the pitch module's reading\n // of number, quality and span together tells that from a descent. The\n // canonical form always carries the flag, whichever way the interval goes.\n const checked = toSpelledInterval(data);\n return new Interval(checked.number, checked.quality, checked.semitones, checked.descending);\n }\n\n /**\n * Rebuild an interval from its {@link Interval.toJSON} output.\n *\n * @param data The serialized interval.\n * @returns The wrapped interval.\n * @throws If the number, quality, and span do not describe the same interval.\n */\n static fromJSON(data: IntervalData): Interval {\n return Interval.fromData(data);\n }\n\n /**\n * Parse an interval name such as `'P5'`, `'m3'`, `'AA4'`, or `'-m3'`.\n *\n * @param name The interval name; a leading `'-'` names the interval taken\n * downward.\n * @returns The interval of that name, descending when the name is prefixed.\n * @throws If the name is not a quality label followed by a diatonic number.\n * Use {@link Interval.tryParse} where failure is ordinary, such as an\n * interval field read on every keystroke.\n */\n static parse(name: string): Interval {\n return unwrapParse(Interval.tryParse(name));\n }\n\n /**\n * Parse an interval name, reporting failure instead of throwing it.\n *\n * The same reading as {@link Interval.parse}, for the callers where a name\n * that does not parse yet is the normal state of the input rather than a\n * fault.\n *\n * @param name The interval name.\n * @returns The interval, or the error explaining why the text is not one.\n * @example\n * ```ts\n * import { Interval } from '@libraz/libcantus';\n * const result = Interval.tryParse('M5');\n * result.ok ? result.value.name : result.error.message; // a major fifth does not exist\n * ```\n */\n static tryParse(name: string): ParseResult<Interval> {\n const parsed = tryParseInterval(name);\n return parsed.ok ? { ok: true, value: Interval.fromData(parsed.value) } : parsed;\n }\n\n /** Diatonic size: 1 = unison, 2 = second, ... 8 = octave, and beyond. */\n get number(): number {\n return this.#number;\n }\n\n /** Quality label: `'P'`, `'M'`, `'m'`, or repeated `'A'`/`'d'`. */\n get quality(): IntervalQualityLabel {\n return this.#quality;\n }\n\n /** Signed semitone span. */\n get semitones(): number {\n return this.#semitones;\n }\n\n /**\n * Whether the interval moves downward. A descending unison spans zero\n * semitones, so this flag is the only record of its direction.\n */\n get isDescending(): boolean {\n return this.#descending;\n }\n\n /**\n * A readable label composed of quality and number, e.g. `'P5'` or `'M3'`,\n * prefixed with `'-'` when the interval descends.\n *\n * The name is written in the grammar {@link Interval.parse} reads, so an\n * interval that has been logged, written to a column, or interpolated into a\n * template comes back as the same interval — direction included.\n */\n get name(): string {\n return `${this.#descending ? '-' : ''}${this.#quality}${this.#number}`;\n }\n\n /** A copy of the underlying plain interval data. */\n get data(): SpelledInterval {\n return this.toJSON();\n }\n\n /**\n * The interval's inversion: the complement that completes the octave.\n *\n * A compound interval is reduced to its simple form first, and the result is\n * always ascending — an inversion answers \"what is left of the octave\",\n * which has no direction of its own. The reduction keeps the octave and its\n * multiples on the octave, so the answer depends on the relation between the\n * two notes and not on how many octaves apart they happen to sit: a double\n * octave inverts to a unison exactly as a single octave does.\n *\n * @returns The inverted interval, e.g. `M3` becomes `m6`.\n * @throws For an augmented octave, whose complement would be a diminished\n * unison: the letters do not move in a unison, so the pitch module reads\n * that relation as the descending `'-A1'` and refuses the name. Every other\n * interval inverts.\n */\n invert(): Interval {\n const numberValue = INVERSION_SUM - simpleDegree(this.#number);\n const quality = invertQuality(this.#quality);\n return Interval.of(numberValue, quality, intervalSemitones(numberValue, quality));\n }\n\n /**\n * The same interval taken in the opposite direction.\n *\n * The number and quality are untouched — only the direction changes, so an\n * ascending major third becomes a descending major third rather than its\n * inversion.\n *\n * @returns The interval with its direction flipped.\n * @example\n * ```ts\n * import { Interval } from '@libraz/libcantus';\n * Interval.parse('M3').negate().toString(); // '-M3'\n * ```\n */\n negate(): Interval {\n // The flag is flipped rather than derived from the negated span: a unison\n // spans zero semitones, whose negation is indistinguishable from itself.\n return new Interval(\n this.#number,\n this.#quality,\n this.#semitones === 0 ? 0 : -this.#semitones,\n !this.#descending,\n );\n }\n\n /**\n * Whether the interval is consonant.\n *\n * @param twoVoice When true, the perfect fourth counts as a dissonance,\n * matching two-voice counterpoint.\n * @returns True if the interval is consonant in that context.\n */\n isConsonant(twoVoice = true): boolean {\n return isConsonantInterval(this.#semitones, twoVoice);\n }\n\n /**\n * Whether another interval is spelled identically.\n *\n * Enharmonic equivalents are not equal: an augmented second and a minor\n * third span the same distance but are different intervals.\n *\n * @param other The interval to compare with.\n * @returns True when number, quality, and span all match.\n */\n equals(other: Interval): boolean {\n // The other interval is read through its public accessors rather than its\n // private fields: a bundler that emits two copies of this class — as a\n // CommonJS build without shared chunks does for the root and /model\n // entries — would otherwise throw on the brand check.\n return (\n this.#number === other.number &&\n this.#quality === other.quality &&\n this.#semitones === other.semitones &&\n this.#descending === other.isDescending\n );\n }\n\n /**\n * The plain interval data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(interval)` from collapsing to `{}`. The result is the\n * canonical shape the pitch module produces: `descending` is always there, so\n * a measured interval, a parsed name, and this method all serialize to the\n * same object and none of them leaves the direction to be guessed.\n *\n * @returns The diatonic number, quality, and semitone span, with `descending`\n * telling which way the interval goes.\n */\n toJSON(): SpelledInterval {\n return {\n number: this.#number,\n quality: this.#quality,\n semitones: this.#semitones,\n descending: this.#descending,\n };\n }\n\n /**\n * The interval's name, so a template literal or a log line reads as the\n * interval.\n *\n * @returns The name, e.g. `'M3'` or `'-M3'` for the same third taken\n * downward.\n */\n toString(): string {\n return this.name;\n }\n}\n","import { InvalidInputError } from '../core/errors/index.js';\nimport type { TimeSignature } from '../core/meter/index.js';\nimport { midiToNote, pitchClassOf as mod12, type Note as NoteData } from '../core/pitch/index.js';\nimport type { NoteEvent } from '../core/types.js';\nimport type { NoteEventAssertOptions } from '../core/validation/index.js';\nimport {\n assertFiniteNumber,\n assertNoteEvents,\n assertTimeSignature,\n} from '../core/validation/index.js';\n\nexport { pitchClassOf as mod12 } from '../core/pitch/index.js';\n\n/**\n * The confidence a key region carries when the caller stated the key.\n *\n * A stated key is not a measurement, and reporting anything less would make a\n * caller's own answer look like a doubtful reading of the notes. Shared by\n * every class that turns a stated key into a region, so the score and the\n * timeline it hands over do not report the same key with two confidences.\n */\nexport const STATED_KEY_CONFIDENCE = 1;\n\n/** How a value that failed a shape check is named in the error explaining it. */\nfunction describeShape(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n return Array.isArray(value) ? 'an array' : typeof value;\n}\n\n/**\n * The value as a data record, refused before any field of it is read.\n *\n * A factory rebuilding a class from stored data reads named fields off its\n * argument, and a project file that lost one — or a `null` where the object\n * should be — would otherwise surface as a `TypeError` from inside the\n * library, which is the shape reserved for the library's own faults. Checking\n * here keeps a malformed document an input error, at the field that is wrong.\n *\n * @param value The value a factory was handed.\n * @param name What the value is called in an error message.\n * @returns The value, typed as the record the caller expects.\n * @throws If the value is not a non-null, non-array object.\n */\nexport function assertDataObject<T>(value: unknown, name: string): T {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new InvalidInputError(`${name} must be an object; received ${describeShape(value)}`);\n }\n return value as T;\n}\n\n/**\n * The value as a data array, refused before it is iterated or spread.\n *\n * @param value The value a factory was handed.\n * @param name What the value is called in an error message.\n * @returns The value, typed as the array the caller expects.\n * @throws If the value is not an array.\n */\nexport function assertDataArray<T>(value: unknown, name: string): readonly T[] {\n if (!Array.isArray(value)) {\n throw new InvalidInputError(`${name} must be an array; received ${describeShape(value)}`);\n }\n return value as readonly T[];\n}\n\n/**\n * The value as an array of data records, every element checked.\n *\n * A hole in a sparse array, an explicit `null`, and a bare number in a list of\n * objects are all refused here rather than at whichever field of the element is\n * read first.\n *\n * @param value The value a factory was handed.\n * @param name What the value is called in an error message.\n * @returns The value, typed as the array the caller expects.\n * @throws If the value is not an array, or an element is not a record.\n */\nexport function assertDataObjects<T>(value: unknown, name: string): readonly T[] {\n const items = assertDataArray<unknown>(value, name);\n for (let index = 0; index < items.length; index += 1) {\n assertDataObject(items[index], `${name}[${index}]`);\n }\n return items as readonly T[];\n}\n\n/**\n * The value as an array of note events, checked as a whole before any one of\n * them is read.\n *\n * A class built from a caller's notes keeps that array as what it is: the notes\n * of a score, the notes of a motif cell, the notes of an arrangement track. So\n * the array is held to the same bound the function API holds it to — the count\n * is capped by the generation budget, and it is capped before the pass over the\n * notes begins, since an array too large to hold is refused for its size rather\n * than after every note in it has been read.\n *\n * One reader for all three, rather than a budget check written again beside\n * each loop: the pairing of \"cap the count\" with \"check each note\" is what went\n * missing on every class path at once when each of them combined the two for\n * itself.\n *\n * @param notes The notes a class was handed.\n * @param name What the array is called in an error message.\n * @param options What counts as an acceptable note here, and the budget to cap\n * the count against; see {@link NoteEventAssertOptions}.\n * @returns The notes, unchanged and uncopied.\n * @throws If the value is not an array, if it holds more notes than the budget\n * allows, or if a note carries a value the library cannot hold.\n */\nexport function assertNoteEventArray(\n notes: unknown,\n name: string,\n options?: NoteEventAssertOptions,\n): readonly NoteEvent[] {\n return assertNoteEvents(assertDataArray<NoteEvent>(notes, name), name, options);\n}\n\n/**\n * Refuse anything but a key where a method takes the key first.\n *\n * These methods read a key and then their options, so an options bag passed\n * on its own is taken for the key. Nothing notices until a `scale` is read off\n * it several calls later, and the error names a field of a key the caller\n * never wrote — `modeMask12 must be finite; received undefined` for an object\n * whose only property is `alternatives`. The shape is checked here instead,\n * where the mistake is still the caller's own argument.\n *\n * Every form a key argument accepts passes: a key name, a plain key/scale, and\n * a value carrying key data. The last two are recognised by their fields rather\n * than by their type, the way every other boundary in the library reads a key,\n * so a `Key` built by a second copy of the module passes. What is left is an\n * object that names no key at all, which is the options bag this guards\n * against; resolving the value is the caller's next step and reports anything\n * that is key-shaped without being a key.\n */\nexport function assertKeyArgument(value: unknown, name: string): void {\n if (value === undefined || typeof value === 'string' || isKeyShaped(value)) {\n return;\n }\n const received =\n value === null ? 'null' : typeof value === 'object' ? 'an object' : `a ${typeof value}`;\n throw new InvalidInputError(\n `${name} must be a Key; received ${received}. A method that also takes options takes them after the key, not in its place`,\n );\n}\n\n/** Whether a value carries the fields any of the key forms is read through. */\nfunction isKeyShaped(value: unknown): boolean {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n return 'scale' in value || 'toJSON' in value || ('rootPc' in value && 'modeMask12' in value);\n}\n\n/** Spell a bare pitch class as an octave-less note with a sharp/flat preference. */\nexport function spellPitchClassBare(pc: number, spelling: 'sharp' | 'flat'): NoteData {\n const spelled = midiToNote(60 + mod12(pc), spelling);\n return { letter: spelled.letter, alter: spelled.alter };\n}\n\n/** Zero with its sign dropped, so `-0` never reaches the plain data. */\nexport function withoutNegativeZero(value: number): number {\n return value === 0 ? 0 : value;\n}\n\n/** Where the last of a run of spans ends, and never before beat 0. */\nexport function spanEnd(...runs: readonly (readonly { endBeat: number }[])[]): number {\n let end = 0;\n for (const run of runs) {\n for (const span of run) {\n end = Math.max(end, span.endBeat);\n }\n }\n return end;\n}\n\n/**\n * Defensive copy of one note event, carrying only the fields a note holds.\n *\n * A `-0` onset survives every arithmetic path that produced it but not\n * `JSON.stringify`, so it is dropped here rather than becoming a value that\n * compares unequal to its own serialization.\n *\n * The event is copied as given: the classes that check their input do so\n * before copying, since what counts as an acceptable note differs between\n * written material and an imported track.\n */\nexport function copyNoteEvent(note: NoteEvent): NoteEvent {\n const copy: NoteEvent = {\n pitch: withoutNegativeZero(note.pitch),\n startBeat: withoutNegativeZero(note.startBeat),\n durationBeat: withoutNegativeZero(note.durationBeat),\n };\n if (note.velocity !== undefined) {\n copy.velocity = withoutNegativeZero(note.velocity);\n }\n if (note.articulation !== undefined) {\n copy.articulation = note.articulation;\n }\n return copy;\n}\n\n/**\n * A defensive copy of a plain time signature, checked the way every meter\n * function checks it.\n *\n * Data arriving from a project file, a plugin, or a hand-edited JSON enters\n * here, so it is held to the rules a parsed signature is held to: an unchecked\n * numerator of zero or of `NaN` would divide every bar that reads it.\n *\n * @param name - What the signature is called in an error message.\n */\nexport function copyTimeSignature(ts: TimeSignature, name?: string): TimeSignature {\n assertDataObject(ts, name ?? 'time signature');\n assertTimeSignature(ts, name);\n const copy: TimeSignature = { numerator: ts.numerator, denominator: ts.denominator };\n if (ts.grouping !== undefined) {\n copy.grouping = [...ts.grouping];\n }\n return copy;\n}\n\n/**\n * How far a plain-data copy follows nesting before it calls the value\n * pathological.\n *\n * Nothing the library holds as data is nested anywhere near this deep, so a\n * value that reaches the limit describes a document built to exhaust the stack\n * rather than music.\n */\nconst MAX_PLAIN_DEPTH = 64;\n\n/**\n * A deep copy of caller data, with every number checked and every absent field\n * left out.\n *\n * The values that reach here are the open-ended ones: the `material` a\n * vocabulary figure is made of, an instrument profile, the records an\n * arrangement's analysis reports. None has a fixed shape, so the only way to\n * promise that nothing non-finite and nothing unserializable reaches a\n * generator — or survives a round trip through a project file — is to walk the\n * value. Dropping `undefined` properties is what keeps the copy equal to its\n * own JSON.\n *\n * A value that refers back to itself, or one nested past\n * {@link MAX_PLAIN_DEPTH} levels, is refused: recursing into either overflows\n * the stack, and a `RangeError` from inside the library is not one of the\n * failures the library documents.\n *\n * @param value The data to copy.\n * @param name What the value is called in an error message.\n * @returns The copy.\n * @throws If a number is not finite, a value is not plain data, or the value\n * is cyclic or pathologically deep.\n */\nexport function copyPlain<T>(value: T, name: string): T {\n return copyPlainAt(value, name, new WeakSet<object>(), 0);\n}\n\n/** One level of {@link copyPlain}, carrying the ancestors and the depth. */\nfunction copyPlainAt<T>(value: T, name: string, seen: WeakSet<object>, depth: number): T {\n if (typeof value === 'number') {\n return assertFiniteNumber(value, name) as T;\n }\n if (typeof value === 'function' || typeof value === 'symbol' || typeof value === 'bigint') {\n throw new InvalidInputError(`${name} must be plain data; received ${typeof value}`);\n }\n if (typeof value !== 'object' || value === null) {\n return value;\n }\n // Only the ancestors are held, not everything already copied, so a record\n // named twice beside itself is copied twice rather than reported as a cycle.\n if (seen.has(value)) {\n throw new InvalidInputError(`${name} must be plain data; received a value referring to itself`);\n }\n if (depth >= MAX_PLAIN_DEPTH) {\n throw new InvalidInputError(\n `${name} must be plain data; received a value nested more than ${MAX_PLAIN_DEPTH} levels deep`,\n );\n }\n seen.add(value);\n try {\n if (Array.isArray(value)) {\n return value.map((item, index) =>\n copyPlainAt(item, `${name}[${index}]`, seen, depth + 1),\n ) as T;\n }\n const copy: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n if (item !== undefined) {\n copy[key] = copyPlainAt(item, `${name}.${key}`, seen, depth + 1);\n }\n }\n return copy as T;\n } finally {\n seen.delete(value);\n }\n}\n\n/**\n * Whether two plain values hold the same data, key order aside.\n *\n * Records, arrays and primitives are all a model class hands out, so one walk\n * answers `equals` for every one of them rather than each class comparing the\n * shapes its own data happens to carry.\n */\nexport function samePlain(value: unknown, other: unknown): boolean {\n if (Array.isArray(value) || Array.isArray(other)) {\n return (\n Array.isArray(value) &&\n Array.isArray(other) &&\n value.length === other.length &&\n value.every((item, index) => samePlain(item, other[index]))\n );\n }\n if (typeof value === 'object' && value !== null && typeof other === 'object' && other !== null) {\n const mine = Object.entries(value);\n const theirs = other as Record<string, unknown>;\n return (\n mine.length === Object.keys(theirs).length &&\n mine.every(([key, item]) => key in theirs && samePlain(item, theirs[key]))\n );\n }\n return value === other;\n}\n","import { InvalidInputError, type ParseResult, unwrapParse } from '../core/errors/index.js';\nimport {\n formatNote,\n type IntervalLike,\n midiToNote,\n type Note as NoteData,\n type NoteNameOptions,\n noteToMidi,\n noteToPitchClass,\n type SpelledInterval,\n spelledInterval,\n toSpelledInterval,\n transposeByInterval,\n transposeNote,\n tryParseNote,\n} from '../core/pitch/index.js';\nimport { MAX_NAME_ACCIDENTALS } from '../core/pitch/naming.js';\nimport { frequencyOf, type TuningTable } from '../core/tuning/index.js';\nimport { describeRejected } from '../core/validation/index.js';\nimport { type KeyLike, pitchToScaleDegree } from '../theory/scale/index.js';\nimport { type TransposingInstrument, toWrittenPitch } from '../theory/transposition/index.js';\nimport { Interval } from './interval.js';\nimport { assertDataObject } from './shared.js';\n\n/**\n * Defensive copy of a plain note, with the letter checked.\n *\n * Formatting and pitch-class arithmetic reduce the letter modulo 7, but\n * `equals` compares it directly: an unreduced letter produces two notes that\n * print the same name and report the same pitch class yet compare unequal.\n */\nfunction copyNote(data: NoteData): NoteData {\n assertDataObject(data, 'note data');\n if (!Number.isInteger(data.letter) || data.letter < 0 || data.letter > 6) {\n throw new InvalidInputError(\n `note letter must be an integer in [0, 6]; received ${data.letter}`,\n );\n }\n const copy: NoteData = { letter: data.letter, alter: data.alter };\n if (data.octave !== undefined) {\n copy.octave = data.octave;\n }\n // Delegate alteration and octave bounds to the same guard used by the core\n // pitch functions. The class must not accept data its own methods reject.\n noteToPitchClass(copy);\n return copy;\n}\n\n/** A bare natural letter name, the only text {@link Note.of} reads. */\nconst NATURAL_LETTER = /^[A-G]$/;\n\n/**\n * The letter number a `Note.of` letter argument names.\n *\n * A letter name is read through the note parser rather than a table of its\n * own, so the letter ordering has one definition. Anything the parser would\n * have to interpret — an accidental, an octave, a non-English glyph — is\n * refused here instead, because `of` builds from parts and `parse` reads text.\n */\nfunction letterNumberOf(letter: number | string): number {\n if (typeof letter === 'number') {\n // Left to copyNote, which rejects the same out-of-range letters a plain\n // note object arriving from outside is rejected for.\n return letter;\n }\n if (!NATURAL_LETTER.test(letter)) {\n throw new InvalidInputError(\n `Note.of takes a letter number 0..6 or a bare letter name 'C'..'B'; received ${describeRejected(letter)}. Use Note.parse(${describeRejected(letter)}) to read a note name with an accidental or an octave.`,\n );\n }\n return unwrapParse(tryParseNote(letter)).letter;\n}\n\n/** The zero-semitone second onto the next letter up, which respells a note. */\nconst DIMINISHED_SECOND: SpelledInterval = {\n number: 2,\n quality: 'd',\n semitones: 0,\n descending: false,\n};\n\n/** The same second taken downwards, onto the letter below. */\nconst DESCENDING_DIMINISHED_SECOND: SpelledInterval = {\n ...DIMINISHED_SECOND,\n descending: true,\n};\n\n/**\n * The number a note is ordered by.\n *\n * The MIDI number where there is an octave to place the note in, and the bare\n * pitch class where there is not — one number per note either way, so a list\n * sorts consistently however its notes were written.\n */\nfunction soundingOrder(note: NoteData): number {\n return note.octave === undefined ? noteToPitchClass(note) : noteToMidi(note);\n}\n\n/**\n * An immutable spelled note: a diatonic letter plus a chromatic alteration and\n * an optional octave. Wraps the plain note object and delegates to the pitch\n * module; every transformation returns a new instance.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.parse('C4').transpose(7).name; // 'G4'\n * ```\n */\nexport class Note {\n readonly #data: NoteData;\n\n /**\n * Wrap a plain note object.\n *\n * @param data The spelled note; it is copied, never retained or mutated.\n * @throws If `letter` is not an integer in 0..6.\n */\n constructor(data: NoteData) {\n this.#data = copyNote(data);\n }\n\n /**\n * Build a note from its parts, without reading any text.\n *\n * The parts are the fields a note holds, so nothing here is interpreted:\n * {@link Note.parse} is what reads `'Bb'` or `'C#4'`, and a letter name given\n * here may carry neither an accidental nor an octave.\n *\n * @param letter The diatonic letter, as a number 0..6 (C..B) or a bare\n * natural letter name `'C'`..`'B'`.\n * @param alter The chromatic alteration in semitones; defaults to natural.\n * @param octave The octave (scientific pitch notation); omit it for a bare\n * pitch class.\n * @returns The note.\n * @throws If the letter is out of range, if a letter name carries an\n * accidental or an octave, or if the alteration or octave is out of range.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.of(1, -1, 4).name; // 'Db4'\n * Note.parse('G').name; // 'G'\n * ```\n */\n static of(letter: number | string, alter = 0, octave?: number): Note {\n const data: NoteData = { letter: letterNumberOf(letter), alter };\n if (octave !== undefined) {\n data.octave = octave;\n }\n return new Note(data);\n }\n\n /**\n * Parse a note name (e.g. `'C#4'`, `'Bb'`, `'F##3'`), in any of the\n * supported note-name systems.\n *\n * The system is detected from the name itself unless one is given, exactly as\n * {@link Key.parse} reads a key name: `'gis'` is a G sharp, while a bare\n * `'B'` is the English B natural until `'german'` says otherwise.\n *\n * @param text The note text.\n * @param opts `system` reads the name in that notation system instead of\n * detecting it.\n * @returns The parsed note.\n * @throws If the text is not a valid note. Use {@link Note.tryParse} where\n * failure is ordinary, such as a note field read on every keystroke.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.parse('gis').name; // 'G#'\n * Note.parse('B', { system: 'german' }).name; // 'Bb'\n * ```\n */\n static parse(text: string, opts?: NoteNameOptions): Note {\n return unwrapParse(Note.tryParse(text, opts));\n }\n\n /**\n * Parse a note name, reporting failure instead of throwing it.\n *\n * The same reading as {@link Note.parse}, for the callers where text that\n * does not name a note yet is the normal state of the input rather than a\n * fault.\n *\n * @param name The note text.\n * @param opts `system` reads the name in that notation system instead of\n * detecting it.\n * @returns The note, or the error explaining why the text is not one.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * const result = Note.tryParse('C#4');\n * result.ok ? result.value.midi : result.error.message; // 61\n * ```\n */\n static tryParse(name: string, opts?: NoteNameOptions): ParseResult<Note> {\n const parsed = tryParseNote(name, opts);\n return parsed.ok ? { ok: true, value: new Note(parsed.value) } : parsed;\n }\n\n /**\n * Name a MIDI number (middle C = C4 = 60) as a note.\n *\n * @param midi The MIDI number.\n * @param spelling Whether to prefer sharps or flats for black keys.\n * @returns The spelled note, with octave.\n */\n static fromMidi(midi: number, spelling: 'sharp' | 'flat' = 'sharp'): Note {\n return new Note(midiToNote(midi, spelling));\n }\n\n /**\n * Wrap an existing plain note object.\n *\n * @param data The plain note.\n * @returns The wrapped note.\n * @throws If `letter` is not an integer in 0..6.\n */\n static fromData(data: NoteData): Note {\n return new Note(data);\n }\n\n /**\n * The note rendered as scientific pitch notation in English, e.g. `'G4'` or\n * `'Bb'`. Use {@link Note.format} to write it in another notation system.\n */\n get name(): string {\n return formatNote(this.#data);\n }\n\n /**\n * The note name written in a notation system.\n *\n * The counterpart of {@link Note.parse}: a getter cannot take an argument, so\n * the system is named here instead of on {@link Note.name}.\n *\n * @param opts `system` writes the name in that notation system instead of\n * English.\n * @returns The note name, including the octave when the note has one.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.parse('G#').format({ system: 'german' }); // 'gis'\n * Note.parse('G#').format({ system: 'japanese' }); // '嬰ト'\n * ```\n */\n format(opts?: NoteNameOptions): string {\n return formatNote(this.#data, opts);\n }\n\n /** The pitch class (0..11), ignoring octave. */\n get pitchClass(): number {\n return noteToPitchClass(this.#data);\n }\n\n /**\n * The MIDI number (middle C = C4 = 60).\n *\n * @throws If the note has no octave and therefore no fixed pitch.\n */\n get midi(): number {\n if (this.#data.octave === undefined) {\n throw new InvalidInputError(`note ${this.name} has no octave, so it has no MIDI number`);\n }\n return noteToMidi(this.#data);\n }\n\n /** The diatonic letter number: 0..6 for C..B. */\n get letter(): number {\n return this.#data.letter;\n }\n\n /** The chromatic alteration in semitones: -1 flat, 0 natural, +1 sharp, ... */\n get alter(): number {\n return this.#data.alter;\n }\n\n /** The octave (scientific pitch notation), or undefined for a bare pitch class. */\n get octave(): number | undefined {\n return this.#data.octave;\n }\n\n /** A copy of the underlying plain note object. */\n get data(): NoteData {\n return copyNote(this.#data);\n }\n\n /**\n * The note's frequency in Hz.\n *\n * The note's MIDI number is read as a step index, which is how the tuning\n * module numbers steps: under twelve divisions the two coincide, and under\n * any other the step index keeps counting from the same reference. A\n * {@link Tuning} carries the three fields this takes, so an instance of it\n * can be passed here directly.\n *\n * @param tuning The temperament to read the note under; twelve-tone equal\n * temperament with A4 = 440 Hz by default.\n * @returns The frequency in Hz.\n * @throws If the note has no octave and therefore no fixed pitch, if the\n * temperament describes no tuning, or if the frequency falls outside the\n * range a number holds.\n * @example\n * ```ts\n * import { Note, Tuning } from '@libraz/libcantus';\n * Note.parse('A4').frequency(); // 440\n * Math.round(Note.parse('C4').frequency()); // 262\n * Note.parse('A4').frequency(Tuning.edo(19)); // 440, the reference step of any EDO\n * ```\n */\n frequency(tuning?: TuningTable): number {\n return frequencyOf(this.midi, tuning);\n }\n\n /**\n * Transpose by a signed number of semitones, keeping the spelling.\n *\n * The letter moves by the diatonic distance of the conventional interval for\n * that many semitones, so `Ab4` up a major second is `Bb4` rather than `A#4`\n * and a flat key stays on the flat side. An octave-less note stays\n * octave-less: only its pitch class is moved. Transposing by zero is the\n * identity: the original spelling is preserved (no enharmonic respelling).\n *\n * @param semitones The signed semitone offset.\n * @param opts `spelling` forces the result onto the sharp or flat side\n * instead of following this note's letter.\n * @returns The transposed note.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.parse('Ab4').transpose(2).name; // 'Bb4'\n * Note.parse('Ab4').transpose(2, { spelling: 'sharp' }).name; // 'A#4'\n * ```\n */\n transpose(semitones: number, opts?: { spelling?: 'sharp' | 'flat' }): Note {\n if (semitones === 0 && opts?.spelling === undefined) {\n return new Note(this.#data);\n }\n return new Note(transposeNote(this.#data, semitones, opts));\n }\n\n /**\n * The spelled interval from this note to another.\n *\n * @param other The second note.\n * @returns The interval, which {@link Interval.toJSON} unwraps to plain data.\n */\n intervalTo(other: Note): Interval {\n // Read the other note through its public accessor rather than its private\n // field: a bundler that emits two copies of this class — as a CommonJS\n // build without shared chunks does for the root and /model entries — would\n // otherwise throw on the brand check.\n return Interval.fromData(spelledInterval(this.#data, other.data));\n }\n\n /**\n * Transpose by a spelled interval, keeping the spelling the interval names.\n *\n * Unlike {@link Note.transpose}, which picks a letter from the semitone\n * count, the interval's diatonic number decides the letter: C up an\n * augmented second is D#, not Eb.\n *\n * @param interval An interval name (e.g. `'A2'`, `'-m3'`), plain interval\n * data, or an {@link Interval}; a descending interval moves down.\n * @returns The transposed note.\n * @example\n * ```ts\n * import { Interval, Note } from '@libraz/libcantus';\n * Note.parse('C4').transposeBy('A2').name; // 'D#4'\n * Note.parse('C4').transposeBy(Interval.parse('A2')).name; // 'D#4'\n * Note.parse('C4').transposeBy('A4').name; // 'F#4', not 'Gb4'\n * ```\n */\n transposeBy(interval: IntervalLike): Note {\n return new Note(transposeByInterval(this.#data, toSpelledInterval(interval)));\n }\n\n /**\n * The same spelled note in another octave.\n *\n * The letter and the alteration are untouched, so this places a note in a\n * register rather than moving it by an interval: `Cb4` given octave 3 is\n * `Cb3`, not the `B3` it sounds as.\n *\n * @param octave The octave (scientific pitch notation), where middle C is C4.\n * @returns The note in that octave.\n * @throws If the octave is not an integer in -100..100.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.parse('C#').withOctave(4).name; // 'C#4'\n * Note.parse('Eb5').withOctave(3).name; // 'Eb3'\n * ```\n */\n withOctave(octave: number): Note {\n return new Note({ letter: this.#data.letter, alter: this.#data.alter, octave });\n }\n\n /**\n * The note a transposing instrument must read to sound this one.\n *\n * The direction is written-side, as {@link Key.forInstrument} is for a key:\n * the part is transposed *away* from what the instrument sounds, so a B flat\n * instrument — which sounds a major second lower than it reads — has a\n * concert C4 written as D4. The interval decides the letter, so a concert\n * E flat 3 reads as C4 on an alto saxophone rather than as B sharp 3.\n *\n * The opposite reading, a written note back to the pitch it sounds, is\n * {@link Note.transposeBy} applied to {@link instrumentTransposition} — the\n * instrument's own written-to-sounding interval.\n *\n * @param instrument A built-in instrument name, or an interval naming a\n * transposition the table does not carry.\n * @returns The note the player reads.\n * @throws If the instrument is neither a known name nor a spelled interval.\n * @example\n * ```ts\n * import { instrumentTransposition, Note } from '@libraz/libcantus';\n * Note.parse('C4').forInstrument('clarinetBb').name; // 'D4'\n * Note.parse('Eb3').forInstrument('altoSax').name; // 'C4'\n * // And back: what a written C4 on a clarinet in A sounds as.\n * Note.parse('C4').transposeBy(instrumentTransposition('clarinetA')).name; // 'A3'\n * ```\n */\n forInstrument(instrument: TransposingInstrument): Note {\n // The same conversion the key uses, so a part and its key signature can\n // never disagree about the direction or the spelling.\n return new Note(toWrittenPitch(this.#data, instrument));\n }\n\n /**\n * The other ways this note can be spelled: the same sounding pitch written on\n * the letter above and on the letter below.\n *\n * A list rather than a single answer, because a note has no one enharmonic\n * partner the way a key has: `C#4` is both `Db4` and `B##3`. Only spellings\n * within a double accidental are offered — the letters two steps away would\n * need a triple one — so a note whose neighbours are unwritable gets a\n * shorter list, and an octave-less note stays octave-less.\n *\n * @returns The alternative spellings, the letter above first.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.parse('C#4').enharmonic().map((note) => note.name); // ['Db4', 'B##3']\n * Note.parse('Cb4').enharmonic().map((note) => note.name); // ['B3']\n * ```\n */\n enharmonic(): Note[] {\n return [DIMINISHED_SECOND, DESCENDING_DIMINISHED_SECOND]\n .map((interval) => transposeByInterval(this.#data, interval))\n .filter((note) => Math.abs(note.alter) <= MAX_NAME_ACCIDENTALS)\n .map((note) => new Note(note));\n }\n\n /**\n * The scale degree this note occupies in a key, counted from 1 at the tonic.\n *\n * The degree is read from the sounding pitch, so an enharmonic spelling\n * answers for the pitch it sounds: in C major both `F#` and `Gb` are outside\n * the scale, and both `B#` and `C` are the tonic.\n *\n * @param key The key to measure against; a key name, a plain key/scale, or a\n * {@link Key}.\n * @returns The 1-based degree, or null when the note is not in the scale.\n * @throws If the value names no key.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.parse('E4').degreeIn('C major'); // 3\n * Note.parse('F#4').degreeIn('C major'); // null\n * ```\n */\n degreeIn(key: KeyLike): number | null {\n // The scale function reports -1 for a pitch it does not contain; the class\n // API says \"no answer\" with null, as `Key.enharmonic` and `Chord.detectBest`\n // do, so a caller cannot read the miss as a degree.\n const degree = pitchToScaleDegree(this.pitchClass, key);\n return degree === -1 ? null : degree;\n }\n\n /**\n * Rebuild a note from its {@link Note.toJSON} output.\n *\n * @param data The serialized note.\n * @returns The wrapped note.\n * @throws If `letter` is not an integer in 0..6.\n */\n static fromJSON(data: NoteData): Note {\n return new Note(data);\n }\n\n /**\n * Order two notes by the pitch they sound, for `Array.prototype.sort`.\n *\n * Sounding pitch, not spelling: an enharmonic pair compares equal, so `C#4`\n * and `Db4` keep the order they were given in while every note that sounds\n * lower comes before them. {@link Note.equals} is the spelling comparison,\n * and the two deliberately disagree about enharmonics.\n *\n * A note carrying an octave is ordered by its MIDI number and an octave-less\n * one by its pitch class, so the octave-less notes of a mixed list gather at\n * the bottom rather than being placed in a register they do not name.\n *\n * @param other The note to compare with.\n * @returns Negative when this note sounds lower, zero when the two sound the\n * same pitch, positive when it sounds higher.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * const notes = [Note.parse('G4'), Note.parse('C4'), Note.parse('E4')];\n * notes.sort((a, b) => a.compareTo(b)).map((note) => note.name); // ['C4', 'E4', 'G4']\n * Note.parse('C#4').compareTo(Note.parse('Db4')); // 0\n * ```\n */\n compareTo(other: Note): number {\n // The other note is read through its public accessor rather than its\n // private field, as `equals` is, so two copies of the class still compare.\n return soundingOrder(this.#data) - soundingOrder(other.data);\n }\n\n /**\n * Whether another note has the same letter, alteration, and octave.\n *\n * @param other The note to compare.\n * @returns True if the spellings are identical.\n */\n equals(other: Note): boolean {\n const b = other.data;\n return (\n this.#data.letter === b.letter &&\n this.#data.alter === b.alter &&\n this.#data.octave === b.octave\n );\n }\n\n /**\n * The plain note data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(note)` from collapsing to `{}`.\n *\n * @returns A copy of the underlying plain note object.\n */\n toJSON(): NoteData {\n return this.data;\n }\n\n /**\n * The note's name, so a template literal or a log line reads as the note.\n *\n * @param opts `system` writes the name in that notation system instead of\n * English, as {@link Key.toString} does for a key.\n * @returns The spelled name, e.g. `'Bb3'`.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * Note.parse('G#4').toString({ system: 'japanese' }); // '嬰ト4'\n * ```\n */\n toString(opts?: NoteNameOptions): string {\n return this.format(opts);\n }\n}\n","import type { ChordToRomanOptions } from '../analyze/functional/index.js';\nimport { chordToRoman } from '../analyze/functional/index.js';\nimport type { KeyRegion, KeyTimelineOptions } from '../analyze/keys/index.js';\nimport { detectModulations, keyLookup, prevailingKeyOf } from '../analyze/keys/index.js';\nimport type { ReducedChord, ReduceProgressionOptions } from '../analyze/reduction/index.js';\nimport { reduceProgression } from '../analyze/reduction/index.js';\nimport type { CadenceHit, ChordTimeline, ChordTimelineOptions } from '../analyze/timeline/index.js';\nimport {\n chordAtBeat,\n chordTimelineFromChords,\n chordTimelineFromNotes,\n detectCadences,\n} from '../analyze/timeline/index.js';\nimport { InvalidInputError } from '../core/errors/index.js';\nimport type { IntervalLike } from '../core/pitch/index.js';\nimport type { KeyScale, NoteEvent } from '../core/types.js';\nimport { assertFiniteNumber, assertRange } from '../core/validation/index.js';\nimport type { ChordSegment, ChordSpan } from '../theory/chord/index.js';\nimport { spanFromChord } from '../theory/chord/index.js';\nimport type { KeyLike, ResolvedKey } from '../theory/scale/index.js';\nimport { resolveKey, scaleOf } from '../theory/scale/index.js';\nimport type { Chord } from './chord.js';\nimport { Chord as ChordClass } from './chord.js';\nimport type { Key } from './key.js';\nimport { keyIdentity, toKey } from './key.js';\nimport { Progression } from './progression.js';\nimport {\n assertDataArray,\n assertDataObject,\n assertKeyArgument,\n STATED_KEY_CONFIDENCE,\n spanEnd,\n} from './shared.js';\n\n/** The plain form a {@link Timeline} hands out and is rebuilt from. */\nexport type TimelineData = {\n segments: ChordSegment[];\n totalBeats: number;\n keys?: KeyRegion[];\n /**\n * How sure the analysis is of each segment's chord, in [0, 1] and in segment\n * order. Carried only by a timeline read from notes: chords a caller placed\n * are not a reading, so a timeline built from them has nothing to report.\n */\n segmentConfidence?: number[];\n};\n\n/**\n * One segment's Roman numeral, with the beats the chord holds it for.\n *\n * A numeral on its own says nothing about when it sounds, and a timed class\n * that answered with a bare list would leave the caller re-deriving the onsets\n * it already holds. The beat range is the segment's own, so a numeral list and\n * a segment list read in step — the shape {@link ReducedChord} already uses.\n */\nexport type TimelineRoman = {\n startBeat: number;\n endBeat: number;\n roman: string;\n};\n\n/** A validated, defensive copy of one chord segment. */\nfunction copySegment(segment: ChordSegment): ChordSegment {\n assertDataObject(segment, 'timeline segment');\n return {\n startBeat: assertFiniteNumber(segment.startBeat, 'timeline segment startBeat'),\n endBeat: assertFiniteNumber(segment.endBeat, 'timeline segment endBeat'),\n // The chord is checked by the same boundary every other chord crosses, so a\n // root of 25 or an interval of NaN is refused or reduced here rather than\n // surfacing wherever the number is finally used.\n chord: new ChordClass(segment.chord).toJSON(),\n };\n}\n\n/** A validated, defensive copy of one key region, pivot chord included. */\nexport function copyKeyRegion(region: KeyRegion): KeyRegion {\n assertDataObject(region, 'key region');\n const copy: KeyRegion = {\n startBeat: assertFiniteNumber(region.startBeat, 'key region startBeat'),\n endBeat: assertFiniteNumber(region.endBeat, 'key region endBeat'),\n // Read through the key itself, so a tonic that does not spell the region's\n // own root is refused here rather than spelling later notes wrongly.\n key: keyIdentity(toKey(region.key)),\n confidence: assertFiniteNumber(region.confidence, 'key region confidence'),\n };\n if (region.modulation !== undefined) {\n copy.modulation = region.modulation;\n }\n if (region.pivot !== undefined) {\n assertDataObject(region.pivot, 'key region pivot');\n copy.pivot = {\n chord: new ChordClass(region.pivot.chord).toJSON(),\n romanFrom: region.pivot.romanFrom,\n romanTo: region.pivot.romanTo,\n };\n }\n return copy;\n}\n\n/**\n * A validated copy of the per-segment confidences, one per segment.\n *\n * The list is meaningless unless it lines up with the segments — it carries no\n * beats of its own and is read by position — so a list of another length is\n * refused rather than silently paired off against the segments it happens to\n * cover.\n */\nfunction copyConfidence(\n confidence: readonly number[] | undefined,\n segments: number,\n): readonly number[] {\n if (confidence === undefined) {\n return [];\n }\n assertDataArray(confidence, 'timeline segmentConfidence');\n if (confidence.length !== segments) {\n throw new InvalidInputError(\n `timeline segmentConfidence must hold one value per segment; received ${confidence.length} for ${segments}`,\n );\n }\n return confidence.map((value, index) =>\n assertRange(value, 0, 1, `timeline segmentConfidence[${index}]`),\n );\n}\n\n/** The part of a span lying inside `[fromBeat, toBeat)`, or null when none does. */\nfunction clipSpan<T extends { startBeat: number; endBeat: number }>(\n span: T,\n fromBeat: number,\n toBeat: number,\n): T | null {\n const startBeat = Math.max(span.startBeat, fromBeat);\n const endBeat = Math.min(span.endBeat, toBeat);\n return endBeat > startBeat ? { ...span, startBeat, endBeat } : null;\n}\n\n/**\n * Harmony that keeps its place in time: chord segments over a span of beats,\n * with the key regions the analysis found under them.\n *\n * This is the timed counterpart of {@link Progression}, which holds an ordered\n * list of chords and deliberately drops their onsets. A piece read from a MIDI\n * track has both a chord order and a chord rhythm, and until now only the order\n * could be held in a class; `Timeline` is where the rhythm lives.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Chord, Key, Progression, Timeline } from '@libraz/libcantus';\n * const timeline = Timeline.fromProgression(\n * new Progression([Chord.parse('C'), Chord.parse('G7')], Key.major('C')),\n * 4,\n * );\n * timeline.at(5)?.symbol(); // 'G7'\n * timeline.roman().map((entry) => entry.roman); // ['I', 'V7']\n * ```\n */\nexport class Timeline {\n readonly #segments: readonly ChordSegment[];\n readonly #totalBeats: number;\n readonly #keys: readonly KeyRegion[];\n readonly #segmentConfidence: readonly number[];\n\n /**\n * Wrap plain timeline data.\n *\n * @param data The segments and the span they cover; copied, never retained.\n * @throws If the span, a segment, or a key region carries a number it cannot\n * hold — a beat that is not finite, a mode mask that names no scale — or if\n * the confidences do not run one per segment.\n */\n constructor(data: TimelineData) {\n assertDataObject(data, 'timeline data');\n this.#segments = Object.freeze(\n assertDataArray<ChordSegment>(data.segments, 'timeline segments').map(copySegment),\n );\n this.#totalBeats = assertRange(\n data.totalBeats,\n 0,\n Number.MAX_SAFE_INTEGER,\n 'timeline totalBeats',\n );\n this.#keys = Object.freeze(\n assertDataArray<KeyRegion>(data.keys ?? [], 'timeline keys').map(copyKeyRegion),\n );\n this.#segmentConfidence = Object.freeze(\n copyConfidence(data.segmentConfidence, this.#segments.length),\n );\n }\n\n /**\n * Build a timeline from placed chords.\n *\n * @param spans The chords with their onsets, in any order.\n * @param totalBeats Where the last chord stops sounding.\n * @param key The key the chords are read in, when it is already known. It\n * becomes the one key region under the whole span; without it the timeline\n * carries no key, and the members that need one say so.\n * @returns The timeline.\n */\n static fromChords(spans: readonly ChordSpan[], totalBeats: number, key?: KeyLike): Timeline {\n const timeline = chordTimelineFromChords(spans, totalBeats);\n const data: TimelineData = { segments: timeline.segments, totalBeats };\n if (key !== undefined) {\n data.keys = [\n {\n // The region starts where the music does, as an inferred one does,\n // so a chord placed in a pickup is covered by the key it sounds in.\n startBeat: timeline.segments[0]?.startBeat ?? 0,\n endBeat: totalBeats,\n key: keyIdentity(toKey(key)),\n confidence: STATED_KEY_CONFIDENCE,\n },\n ];\n }\n return new Timeline(data);\n }\n\n /**\n * Infer a timeline from sounding notes.\n *\n * @param notes The note events to read.\n * @param opts The options {@link chordTimelineFromNotes} accepts.\n * @returns The inferred timeline, carrying the key regions the analysis found.\n */\n static fromNotes(notes: readonly NoteEvent[], opts?: ChordTimelineOptions): Timeline {\n const { timeline, keys, segmentConfidence } = chordTimelineFromNotes(notes, opts);\n // The analysis reports where the chords and the keys end rather than the\n // span it ran over, so the span is read back off them unless it was given.\n const totalBeats = opts?.totalBeats ?? spanEnd(timeline.segments, keys);\n return new Timeline({ segments: timeline.segments, totalBeats, keys, segmentConfidence });\n }\n\n /**\n * Place a progression's chords on a regular grid.\n *\n * The chords cross over as harmony alone: a spelling one of them carried is\n * dropped, since a chord placed on the grid is a `ChordSpan` and a span\n * carries none. A carried key becomes the one key region under the span,\n * spelled tonic and scale form included — an Ab minor comes back Ab minor,\n * which is what the numerals over the region are read from.\n *\n * @param progression The chords, in order.\n * @param beatsEach How long each chord sounds.\n * @returns The timeline.\n * @throws If `beatsEach` is not a positive finite number of beats.\n */\n static fromProgression(progression: Progression, beatsEach: number): Timeline {\n assertRange(beatsEach, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, 'timeline beatsEach');\n const chords = progression.chords;\n const spans = chords.map((chord, index) => spanFromChord(chord.data, index * beatsEach));\n const totalBeats = chords.length * beatsEach;\n const key = progression.key;\n return key === undefined\n ? Timeline.fromChords(spans, totalBeats)\n : Timeline.fromChords(spans, totalBeats, key);\n }\n\n /** Rebuild a timeline from the plain data {@link Timeline.data} hands out. */\n static fromData(data: TimelineData): Timeline {\n return new Timeline(data);\n }\n\n /** Rebuild a timeline from its {@link Timeline.toJSON} output. */\n static fromJSON(data: TimelineData): Timeline {\n return new Timeline(data);\n }\n\n /**\n * The chord sounding at a beat, or null where nothing is.\n *\n * A segment covers `[startBeat, endBeat)`, so the beat a chord gives way on\n * answers with the chord arriving rather than the one leaving. The chord\n * carries the key in force at that beat when the timeline knows one, so it\n * can name its own numeral and function.\n *\n * @param beat The beat to read.\n * @returns The chord, or null outside every segment.\n * @throws If `beat` is not finite.\n */\n at(beat: number): Chord | null {\n const chord = chordAtBeat(this.#segments, beat);\n if (chord === null) {\n return null;\n }\n const key = this.#keyAt(beat);\n return key === undefined ? new ChordClass(chord) : new ChordClass(chord, key);\n }\n\n /** The chord segments, in time order. */\n get segments(): readonly ChordSegment[] {\n return this.#copySegments();\n }\n\n /** Where the last chord stops sounding. */\n get totalBeats(): number {\n return this.#totalBeats;\n }\n\n /** The key held longest across the span, when the analysis found one. */\n get key(): Key | undefined {\n const prevailing = prevailingKeyOf(this.#keys);\n return prevailing === null ? undefined : toKey(prevailing);\n }\n\n /**\n * Every key region under the span, in time order.\n *\n * These are the regions the timeline was built with: the ones\n * {@link Timeline.fromNotes} read off the notes, or the single region a key\n * given to {@link Timeline.fromChords} describes. A timeline holding chords\n * alone carries none until it is asked to read them —\n * {@link Timeline.modulations} is where the chords are searched for the keys\n * they imply.\n */\n get keys(): readonly KeyRegion[] {\n return this.#keys.map(copyKeyRegion);\n }\n\n /**\n * How sure the analysis is of each segment's chord, in [0, 1] and in segment\n * order, so a reading is paired with the segment it describes by position.\n *\n * A confidence answers the question a chord symbol cannot: whether the notes\n * really spell that chord, or whether a passing figure was the best of a bad\n * set of candidates. Empty on a timeline whose chords were placed rather than\n * inferred — {@link Timeline.fromChords} and {@link Timeline.fromProgression}\n * are given the harmony, so there is no reading to report.\n *\n * @example\n * ```ts\n * import { Timeline } from '@libraz/libcantus';\n * const timeline = Timeline.fromNotes([\n * { pitch: 60, startBeat: 0, durationBeat: 4 },\n * { pitch: 64, startBeat: 0, durationBeat: 4 },\n * { pitch: 67, startBeat: 0, durationBeat: 4 },\n * ]);\n * timeline.segmentConfidence.length === timeline.length; // true\n * ```\n */\n get segmentConfidence(): readonly number[] {\n return [...this.#segmentConfidence];\n }\n\n /** How many segments the timeline holds. */\n get length(): number {\n return this.#segments.length;\n }\n\n /** Iterate the segments in time order, so a timeline works with `for...of`. */\n [Symbol.iterator](): IterableIterator<ChordSegment> {\n return this.#copySegments()[Symbol.iterator]();\n }\n\n /**\n * Drop the time axis, keeping the chord order.\n *\n * Explicit rather than implicit, because the onsets are information and\n * losing them silently is how a chord rhythm disappears from a pipeline. A\n * rest between two segments goes with them: the chords either side become\n * neighbours in the progression.\n *\n * @returns The chords in order, carrying the prevailing key when there is one.\n */\n progression(): Progression {\n const chords = this.#segments.map((segment) => new ChordClass(segment.chord));\n const key = this.key;\n return key === undefined ? new Progression(chords) : new Progression(chords, key);\n }\n\n /**\n * The structural chords behind the surface harmony.\n *\n * @param opts Which reading decides the frame; see\n * {@link ReduceProgressionOptions}.\n * @returns One labelled chord per segment, in time order.\n * @throws If the timeline carries no key region to read the chords against.\n */\n reduce(opts?: ReduceProgressionOptions): ReducedChord[] {\n return reduceProgression(this.chordTimeline, this.#keyContext(), opts);\n }\n\n /**\n * The cadences the harmony arrives at.\n *\n * Each hit carries the beat it arrives on as well as the cadence itself: a\n * cadence without its onset says that the music cadenced but not where, which\n * is the one thing a timed class is holding that a chord pair is not.\n *\n * @returns The cadences found, in time order.\n * @throws If the timeline carries no key region to read the chords against.\n */\n cadences(): CadenceHit[] {\n return detectCadences(this.chordTimeline, this.#keyContext());\n }\n\n /**\n * The keys the chords themselves imply, in time order.\n *\n * The chord route to key regions, for a timeline that holds harmony without\n * the notes it was played from — a lead sheet, or a progression laid out in\n * time. A chord argues for a key far more strongly than its three or four\n * pitch classes do, so a modulation is read off the chords rather than off a\n * pitch-class profile, and the chord that reads in both keys is reported as\n * the pivot the modulation turned on.\n *\n * The regions are searched for here rather than kept on the timeline:\n * {@link Timeline.keys} answers with what the timeline was built with, which\n * for placed chords is the key the caller stated or nothing at all.\n *\n * @param opts Analysis options; see {@link KeyTimelineOptions}.\n * @returns The key regions the chords imply; empty when there are no chords.\n * @example\n * ```ts\n * import { Chord, Key, Progression, Timeline } from '@libraz/libcantus';\n * const progression = new Progression(\n * [Chord.parse('C'), Chord.parse('G7'), Chord.parse('C')],\n * Key.major('C'),\n * );\n * Timeline.fromProgression(progression, 4).modulations().length; // 1\n * ```\n */\n modulations(opts?: KeyTimelineOptions): KeyRegion[] {\n return detectModulations(this.#copySegments(), {\n totalBeats: this.#totalBeats,\n ...opts,\n }).map(copyKeyRegion);\n }\n\n /**\n * The chords as roman numerals in a key.\n *\n * @param key Key to read the chords in; falls back to the key in force at\n * each segment, so a timeline that modulates names every chord in the key\n * it actually sounds in.\n * @param opts Applied-numeral rendering options; see\n * {@link ChordToRomanOptions}.\n * @returns One numeral per segment, with the beats it holds for.\n * @throws If no key is given and the timeline carries none.\n */\n roman(key?: KeyLike, opts?: ChordToRomanOptions): TimelineRoman[] {\n assertKeyArgument(key, 'timeline key');\n // The key a caller names travels whole: a numeral is written from the\n // degrees the key spells, so an Ab minor read through its pitch classes\n // alone would be numbered as the G# minor those read best as.\n const given = key === undefined ? undefined : resolveKey(key);\n const keyAt = given === undefined ? this.#resolvedKeyAt() : () => given;\n return this.#segments.map((segment) => ({\n startBeat: segment.startBeat,\n endBeat: segment.endBeat,\n roman: chordToRoman(segment.chord, keyAt(segment.startBeat), opts),\n }));\n }\n\n /**\n * The stretch of the timeline between two beats.\n *\n * Beats are kept as they are rather than rebased on the slice, so a sliced\n * timeline still lines up with the score it was read from; `totalBeats`\n * becomes where the slice ends. A segment or key region straddling an edge is\n * clipped to it, and one reduced to nothing is dropped.\n *\n * @param fromBeat First beat of the stretch.\n * @param toBeat End of the stretch, exclusive.\n * @returns The clipped timeline.\n * @throws If either beat is not finite, or `toBeat` precedes `fromBeat`.\n */\n slice(fromBeat: number, toBeat: number): Timeline {\n assertFiniteNumber(fromBeat, 'timeline slice fromBeat');\n assertFiniteNumber(toBeat, 'timeline slice toBeat');\n if (toBeat < fromBeat) {\n throw new InvalidInputError(\n `timeline slice toBeat must not precede fromBeat; received [${fromBeat}, ${toBeat})`,\n );\n }\n const clip = <T extends { startBeat: number; endBeat: number }>(spans: readonly T[]): T[] =>\n spans\n .map((span) => clipSpan(span, fromBeat, toBeat))\n .filter((span): span is T => span !== null);\n // The confidences travel with the segments they describe: they are read by\n // position, so dropping a segment without dropping its reading would shift\n // every later one onto the wrong chord.\n const kept = this.#segments\n .map((segment, index) => ({ segment, index }))\n .filter(({ segment }) => clipSpan(segment, fromBeat, toBeat) !== null);\n const data: TimelineData = {\n segments: clip(this.#segments),\n totalBeats: Math.max(0, Math.min(toBeat, this.#totalBeats)),\n keys: clip(this.#keys),\n };\n if (this.#segmentConfidence.length > 0) {\n data.segmentConfidence = kept.map(({ index }) => this.#segmentConfidence[index] ?? 0);\n }\n return new Timeline(data);\n }\n\n /**\n * The timeline moved by a number of semitones.\n *\n * The key regions move with the chords, so every segment keeps the degree and\n * function it had in the key it sounded in.\n *\n * @param semitones The signed semitone offset.\n * @returns The transposed timeline.\n */\n transpose(semitones: number): Timeline {\n return this.#moved(\n (chord) => chord.transpose(semitones),\n (key) => key.transpose(semitones),\n );\n }\n\n /**\n * The timeline moved by a spelled interval, keeping the spelling.\n *\n * Unlike {@link Timeline.transpose}, which picks letters from a semitone\n * count, the interval's diatonic number decides them: a chord taken up an\n * augmented fourth is spelled with sharps and one taken up a diminished fifth\n * with flats.\n *\n * Only a chord carrying a spelling of its own is spelled that way. A key\n * region holds a key/scale rather than a spelled key, so a chord that takes\n * its letters from the key in force follows the spelling that scale reads\n * best from, whichever interval moved it there.\n *\n * @param interval An interval name (e.g. `'A4'`, `'-m3'`), plain interval\n * data, or an {@link Interval}; a descending interval moves down.\n * @returns The transposed timeline.\n */\n transposeBy(interval: IntervalLike): Timeline {\n return this.#moved(\n (chord) => chord.transposeBy(interval),\n (key) => key.transposeBy(interval),\n );\n }\n\n /**\n * Whether another timeline holds the same chords over the same span.\n *\n * The key regions are not compared: they are an analysis lens over the\n * chords, the way a {@link Progression}'s key context is over its own.\n *\n * @param other The timeline to compare.\n * @returns True when the segments and the span both match.\n */\n equals(other: Timeline): boolean {\n const theirs = other.data;\n if (theirs.totalBeats !== this.#totalBeats || theirs.segments.length !== this.length) {\n return false;\n }\n return this.#segments.every((segment, index) => {\n const mine = segment;\n const yours = theirs.segments[index];\n return (\n yours !== undefined &&\n mine.startBeat === yours.startBeat &&\n mine.endBeat === yours.endBeat &&\n new ChordClass(mine.chord).equals(new ChordClass(yours.chord))\n );\n });\n }\n\n /** A copy of the underlying plain data. */\n get data(): TimelineData {\n const data: TimelineData = {\n segments: this.#copySegments(),\n totalBeats: this.#totalBeats,\n };\n // Omitted rather than written as an empty list, so a timeline built without\n // a key serializes to the segments and the span alone.\n if (this.#keys.length > 0) {\n data.keys = this.#keys.map(copyKeyRegion);\n }\n if (this.#segmentConfidence.length > 0) {\n data.segmentConfidence = [...this.#segmentConfidence];\n }\n return data;\n }\n\n /** The plain form of the timeline, for `JSON.stringify`. */\n toJSON(): TimelineData {\n return this.data;\n }\n\n /** The `{ at, segments }` shape the analysis functions take. */\n get chordTimeline(): ChordTimeline {\n const segments = this.#copySegments();\n return { at: (beat) => chordAtBeat(segments, beat), segments };\n }\n\n /** A fresh copy of the segments, which is what every reader is handed. */\n #copySegments(): ChordSegment[] {\n return this.#segments.map(copySegment);\n }\n\n /** The key in force at a beat, or undefined when the timeline knows none. */\n #keyAt(beat: number): Key | undefined {\n const prevailing = prevailingKeyOf(this.#keys);\n return prevailing === null ? undefined : toKey(keyLookup(this.#keys, prevailing)(beat));\n }\n\n /**\n * The key every beat of the timeline is read against, spelling and all.\n *\n * A lookup rather than one key, so a timeline that modulates has each chord\n * read in the key it sounds in; beats outside every region fall back to the\n * prevailing key. The regions carry a spelled tonic and a scale form, and\n * this hands them on as they are: an Ab minor is where a German sixth is\n * named from — `Fb Ab Cb D` — and reading it through its pitch classes alone\n * would number it as the G# minor those read best as.\n */\n #resolvedKeyAt(): (beat: number) => ResolvedKey {\n const prevailing = prevailingKeyOf(this.#keys);\n if (prevailing === null) {\n throw new InvalidInputError(\n 'timeline carries no key; build it from notes, or pass a key to Timeline.fromChords',\n );\n }\n return keyLookup(this.#keys, prevailing);\n }\n\n /**\n * The pitch classes of that key, for the readings that want them.\n *\n * A reduction and a cadence are read from which notes are in the key rather\n * than from how the key is written, so they take the scale; the reduction is\n * where the drop is stated rather than in the lookup, which is what let the\n * numerals lose the spelling by sharing it.\n */\n #keyContext(): (beat: number) => KeyScale {\n const keyAt = this.#resolvedKeyAt();\n return (beat) => scaleOf(keyAt(beat));\n }\n\n /** Move every chord and every key region by the same step. */\n #moved(moveChord: (chord: Chord) => Chord, moveKey: (key: Key) => Key): Timeline {\n const segments = this.#segments.map((segment) => ({\n startBeat: segment.startBeat,\n endBeat: segment.endBeat,\n chord: moveChord(new ChordClass(segment.chord)).toJSON(),\n }));\n const keys = this.#keys.map((region) => {\n const moved: KeyRegion = {\n ...region,\n key: keyIdentity(moveKey(toKey(region.key))),\n };\n if (region.pivot !== undefined) {\n // The numerals a pivot carries are degrees, so they survive the move;\n // only the chord they name has to travel with the keys.\n moved.pivot = {\n ...region.pivot,\n chord: moveChord(new ChordClass(region.pivot.chord)).toJSON(),\n };\n }\n return moved;\n });\n const data: TimelineData = { segments, totalBeats: this.#totalBeats, keys };\n // Transposition moves the chords without re-reading them, so each segment\n // is exactly as well attested where it lands as where it came from.\n if (this.#segmentConfidence.length > 0) {\n data.segmentConfidence = [...this.#segmentConfidence];\n }\n return new Timeline(data);\n }\n}\n","import {\n type AnalyzeChordOptions,\n type CadenceResult,\n type ChordAnalysis,\n type ChordToRomanOptions,\n type DetectCadenceOptions,\n detectCadence,\n type HarmonicFunction,\n} from '../analyze/functional/index.js';\nimport { InvalidInputError } from '../core/errors/index.js';\nimport type { IntervalLike } from '../core/pitch/index.js';\nimport type { SubstituteOptions, SubstitutionType } from '../generate/reharmony/index.js';\nimport { substituteChord } from '../generate/reharmony/index.js';\nimport type { Chord as ChordData, ChordSpan } from '../theory/chord/index.js';\nimport { chordFromSpan } from '../theory/chord/index.js';\nimport { type ScaleChoice, scalesForChanges } from '../theory/chordscale/index.js';\nimport type { KeyLike } from '../theory/scale/index.js';\nimport { type VoicingOptions, voiceProgression } from '../theory/voicing/index.js';\nimport type { Chord } from './chord.js';\nimport { Chord as ChordClass } from './chord.js';\nimport type { Key, KeyData } from './key.js';\nimport { Key as KeyClass, toKey } from './key.js';\nimport {\n assertDataArray,\n assertDataObject,\n assertDataObjects,\n assertKeyArgument,\n} from './shared.js';\nimport { Timeline } from './timeline.js';\n\n/**\n * The plain form of a {@link Progression}: the chords as plain data, and the\n * carried key as its own plain data when the progression has one.\n */\nexport type ProgressionData = { chords: ChordData[]; key: KeyData | undefined };\n\n/**\n * An immutable ordered sequence of chords, optionally carrying a {@link Key}\n * context shared by its analysis methods.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * const key = Key.major('C');\n * key.chord(2).progressionTo(key.chord(5), key.chord(1)).roman();\n * // ['ii', 'V', 'I']\n * ```\n */\nexport class Progression {\n readonly #chords: readonly Chord[];\n readonly #key: Key | undefined;\n\n /**\n * Wrap a chord sequence.\n *\n * @param chords The chords in order; the array is copied.\n * @param key Optional key context for analysis methods, in whatever form the\n * caller holds it: a key name, a plain key/scale, or a {@link Key}.\n */\n constructor(chords: readonly Chord[], key?: KeyLike) {\n assertKeyArgument(key, 'progression key');\n const resolved = key === undefined ? undefined : toKey(key);\n this.#chords = Object.freeze(Progression.#attachKey(chords, resolved));\n this.#key = resolved;\n }\n\n /**\n * Attach the progression key to every chord member.\n *\n * The key is applied unconditionally, including to chords that already carry\n * one, so the members never disagree with the progression about which key\n * spells them and a re-key during a modulation reaches all of them.\n * {@link Chord.withKey} keeps a spelling the caller supplied and re-derives\n * the rest, so the result depends on neither the chords' previous key nor the\n * number of times a key was attached.\n */\n static #attachKey(chords: readonly Chord[], key: Key | undefined): Chord[] {\n const given = assertDataObjects<Chord>(chords, 'progression chords');\n return key === undefined ? [...given] : given.map((chord) => chord.withKey(key));\n }\n\n /**\n * Start from a chord sequence, matching the `of` factory on the other\n * classes.\n *\n * The same reading as the constructor, so a progression reads like\n * `Chord.of` and `Score.of` do at the point it is built.\n *\n * @param chords The chords in order; the array is copied.\n * @param key Optional key context for the analysis methods.\n * @returns The progression.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * Progression.of([Chord.parse('C'), Chord.parse('G7')], Key.major('C')).roman();\n * // ['I', 'V7']\n * ```\n */\n static of(chords: readonly Chord[], key?: KeyLike): Progression {\n return new Progression(chords, key);\n }\n\n /**\n * Build a progression from the {@link ChordSpan} records the generators\n * return, keeping their order.\n *\n * The spans' `startBeat`, `degree`, and `secondaryDominant` are analysis\n * annotations that a chord sequence does not carry; only the harmony crosses\n * over. Keep the spans themselves if the timing matters.\n *\n * @param spans The chord spans, in order.\n * @param key Optional key context for the analysis methods.\n * @returns The progression.\n * @example\n * ```ts\n * import { generateProgression, Key, Progression } from '@libraz/libcantus';\n * const key = Key.major('C');\n * const spans = generateProgression({ key, style: 'dance', bars: 4 });\n * Progression.fromSpans(spans, key).roman();\n * ```\n */\n static fromSpans(spans: readonly ChordSpan[], key?: KeyLike): Progression {\n const chords = assertDataObjects<ChordSpan>(spans, 'progression spans').map((span) =>\n ChordClass.fromData(chordFromSpan(span)),\n );\n return new Progression(chords, key);\n }\n\n /**\n * Rebuild a progression from its {@link Progression.toJSON} output.\n *\n * @param data The serialized chords and key.\n * @returns The progression.\n */\n static fromJSON(data: ProgressionData): Progression {\n assertDataObject(data, 'progression data');\n const key = data.key === undefined ? undefined : KeyClass.fromJSON(data.key);\n const chords = assertDataArray<ChordData>(data.chords, 'progression chords').map((chord) =>\n ChordClass.fromJSON(chord),\n );\n return key === undefined ? new Progression(chords) : new Progression(chords, key);\n }\n\n /**\n * Wrap plain progression data, matching the `fromData` factory on the other\n * classes.\n *\n * @param data The plain progression, as {@link Progression.data} hands it out.\n * @returns The progression.\n */\n static fromData(data: ProgressionData): Progression {\n return Progression.fromJSON(data);\n }\n\n /**\n * The chord sequence.\n *\n * The array is the progression's own and is frozen rather than copied, so\n * reading it in a loop stays linear.\n */\n get chords(): readonly Chord[] {\n return this.#chords;\n }\n\n /** The carried key context, if any. */\n get key(): Key | undefined {\n return this.#key;\n }\n\n /**\n * A copy of the underlying plain progression data: the chords as plain\n * objects and the carried key, if any, as its own plain data.\n */\n get data(): ProgressionData {\n return this.toJSON();\n }\n\n /** The number of chords. */\n get length(): number {\n return this.#chords.length;\n }\n\n /**\n * The chord at an index.\n *\n * @param index 0-based position; a negative index counts from the end.\n * @returns The chord, or undefined when the index is out of range.\n */\n at(index: number): Chord | undefined {\n return this.#chords.at(index);\n }\n\n /** Iterate the chords in order, so a progression works with `for...of`. */\n [Symbol.iterator](): IterableIterator<Chord> {\n return this.#chords[Symbol.iterator]();\n }\n\n /**\n * Whether another progression holds the same chords in the same order.\n *\n * The key context is not compared: it is an analysis lens, not part of the\n * harmony. Chord equality follows {@link Chord.equals}.\n *\n * @param other The progression to compare.\n * @returns True when the chord sequences match.\n */\n equals(other: Progression): boolean {\n if (this.#chords.length !== other.length) {\n return false;\n }\n return this.#chords.every((chord, index) => {\n const theirs = other.at(index);\n return theirs !== undefined && chord.equals(theirs);\n });\n }\n\n /**\n * A copy of this progression with a chord appended.\n *\n * @param chord The chord to append.\n * @returns The new progression.\n */\n add(chord: Chord): Progression {\n return new Progression([...this.#chords, chord], this.#key);\n }\n\n /**\n * A new progression with every chord replaced by what `fn` returns for it.\n *\n * The result is a progression rather than an array, and it carries this\n * progression's key context, so a transformation stays inside the class\n * instead of dropping out of it and having to be rebuilt. This progression is\n * untouched.\n *\n * The key reaches the returned chords the way the constructor attaches it, so\n * a chord `fn` built without one is still spelled and analyzed in this key.\n *\n * @param fn Called with each chord and its 0-based index.\n * @returns The mapped progression.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * const progression = new Progression([Chord.parse('C'), Chord.parse('G')], Key.major('C'));\n * const moved = progression.map((chord) => chord.transpose(2));\n * moved.toString(); // 'D A'\n * moved.key?.toString(); // 'C major'\n * progression.toString(); // 'C G' — the original is unchanged\n * ```\n */\n map(fn: (chord: Chord, index: number) => Chord): Progression {\n return new Progression(\n this.#chords.map((chord, index) => fn(chord, index)),\n this.#key,\n );\n }\n\n /**\n * A new progression holding only the chords `pred` accepts, in order.\n *\n * The key context travels with them and this progression is untouched.\n *\n * @param pred Called with each chord and its 0-based index.\n * @returns The filtered progression, empty when nothing is accepted.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * const progression = new Progression(\n * [Chord.parse('C'), Chord.parse('Am'), Chord.parse('F'), Chord.parse('G')],\n * Key.major('C'),\n * );\n * progression.filter((chord) => chord.quality === 'maj').toString(); // 'C F G'\n * ```\n */\n filter(pred: (chord: Chord, index: number) => boolean): Progression {\n return new Progression(\n this.#chords.filter((chord, index) => pred(chord, index)),\n this.#key,\n );\n }\n\n /**\n * A stretch of this progression, as a progression carrying the same key.\n *\n * The bounds read as `Array.prototype.slice` reads them: `end` is exclusive,\n * a negative index counts from the end, and an omitted bound runs to the edge.\n *\n * @param start First chord of the stretch; defaults to the beginning.\n * @param end One past the last chord; defaults to the end.\n * @returns The sliced progression.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * const progression = new Progression(\n * [Chord.parse('C'), Chord.parse('Am'), Chord.parse('F')],\n * Key.major('C'),\n * );\n * progression.slice(1).toString(); // 'Am F'\n * progression.slice(0, 2).toString(); // 'C Am'\n * ```\n */\n slice(start?: number, end?: number): Progression {\n return new Progression(this.#chords.slice(start, end), this.#key);\n }\n\n /**\n * This progression followed by another run of chords.\n *\n * The result carries this progression's key context; a key the other\n * progression carried is dropped, because two keys cannot both analyze one\n * chord sequence. Re-key the result with {@link Progression.withKey} where the\n * second run is the one to read it in.\n *\n * @param other The chords to append, as a progression or a plain array.\n * @returns The joined progression.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * const key = Key.major('C');\n * key.progression('I', 'vi').concat(key.progression('IV', 'V')).roman();\n * // ['I', 'vi', 'IV', 'V']\n * ```\n */\n concat(other: Progression | readonly Chord[]): Progression {\n // Read structurally rather than with `instanceof`: the package ships an ESM\n // and a CommonJS build, so a consumer reaching the two through different\n // conditions holds two `Progression` classes.\n const chords: readonly Chord[] = 'chords' in other ? other.chords : other;\n return new Progression([...this.#chords, ...chords], this.#key);\n }\n\n /**\n * The position of the first chord equal to `chord`.\n *\n * Equality is {@link Chord.equals}, not reference identity, so a chord built\n * separately is found as long as it names the same harmony.\n *\n * @param chord The chord to look for.\n * @returns The 0-based position, or -1 when the progression holds no such\n * chord.\n * @example\n * ```ts\n * import { Chord, Progression } from '@libraz/libcantus';\n * const progression = new Progression([Chord.parse('C'), Chord.parse('G7')]);\n * progression.indexOf(Chord.of('G', 'dom7')); // 1\n * progression.indexOf(Chord.parse('F')); // -1\n * ```\n */\n indexOf(chord: Chord): number {\n return this.#chords.findIndex((mine) => mine.equals(chord));\n }\n\n /**\n * A copy of this progression carrying the given key context.\n *\n * @param key The key context to attach; a key name, a plain key/scale, or a\n * {@link Key}.\n * @returns The new progression.\n */\n withKey(key: KeyLike): Progression {\n return new Progression(this.#chords, key);\n }\n\n /**\n * Voice the progression with smooth voice leading.\n *\n * @param opts Voicing options; defaults to four SATB voices.\n * @returns One ascending voicing (MIDI pitches) per chord.\n * @throws If any chord admits no voicing within the given ranges.\n */\n voice(opts?: VoicingOptions): number[][] {\n // The carried key travels whole, as it does through every other method\n // here: the voicer spells the chords it scores, so a progression in Ab\n // minor voiced through its pitch classes alone would be led by the sharps\n // of a G# minor.\n const key = opts?.key ?? this.#key;\n return voiceProgression(\n this.#chords.map((chord) => chord.data),\n key === undefined ? opts : { ...opts, key },\n );\n }\n\n /**\n * The Roman numeral of each chord in a key.\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @param opts Applied-numeral rendering options.\n * @returns One numeral per chord.\n * @throws If no key is given and none is carried.\n */\n roman(key?: KeyLike, opts?: ChordToRomanOptions): string[] {\n const resolved = this.#resolveKey(key);\n return this.#chords.map((chord) => chord.roman(resolved, opts));\n }\n\n /**\n * The harmonic function of each chord in a key.\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @returns One function per chord.\n * @throws If no key is given and none is carried.\n */\n functions(key?: KeyLike): HarmonicFunction[] {\n const resolved = this.#resolveKey(key);\n return this.#chords.map((chord) => chord.function(resolved));\n }\n\n /**\n * Analyze every chord and classify the closing cadence.\n *\n * The cadence is detected on the final chord pair and is null when the\n * progression has fewer than two chords.\n *\n * The options reach both analyses: `applied` and `alternatives` go to every\n * chord, and `voicing` — the pitches sounding under the progression, one\n * voicing per chord as {@link Progression.voice} produces them — to the\n * cadence, which cannot tell a perfect authentic cadence from an imperfect\n * one without knowing the soprano. It is the same shape\n * {@link Progression.cadences} takes, and the closing pair is cut from it\n * here; a two-element array is read as that pair itself.\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @param opts Applied-numeral rendering options, `alternatives` for the\n * readings both analyses turned down, and `voicing` for the cadence's\n * voice-leading detail; see {@link AnalyzeChordOptions} and\n * {@link DetectCadenceOptions}.\n * @returns Per-chord analyses and the closing cadence.\n * @throws If no key is given and none is carried.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * const progression = new Progression([Chord.parse('G7'), Chord.parse('C')], Key.major('C'));\n * progression.analyze(undefined, { voicing: progression.voice() }).cadence?.strength;\n * // 'perfect'\n * ```\n */\n analyze(\n key?: KeyLike,\n // `voicing` is widened off the cadence options so that this entry and\n // `cadences` name one type for one field: the pitches under the whole\n // progression, which is what `voice()` hands back.\n opts?: AnalyzeChordOptions & Omit<DetectCadenceOptions, 'voicing'> & { voicing?: number[][] },\n ): { chords: ChordAnalysis[]; cadence: CadenceResult | null } {\n const resolved = this.#resolveKey(key);\n const chords = this.#chords.map((chord) => chord.analyze(resolved, opts));\n // The whole-progression voicing is cut to the closing pair below, so it is\n // held apart from the options that reach the cadence unchanged.\n const { voicing, ...cadenceOpts } = opts ?? {};\n const from = this.#chords[this.#chords.length - 2];\n const to = this.#chords[this.#chords.length - 1];\n // The chord before the closing pair is supplied from the progression\n // itself, exactly as `cadences` supplies it, so a cadential six-four is\n // reported as one event by both and the two never explain the same final\n // pair differently. A caller's own `approach` still reaches a progression\n // too short to have one of its own.\n const approach = this.#chords[this.#chords.length - 3];\n const cadence =\n from !== undefined && to !== undefined\n ? detectCadence(from.data, to.data, resolved, {\n ...cadenceOpts,\n ...(approach === undefined ? {} : { approach: approach.data }),\n ...(voicing === undefined ? {} : { voicing: this.#closingVoicing(voicing) }),\n })\n : null;\n return { chords, cadence };\n }\n\n /**\n * The two voicings of the closing pair, cut from the progression's own.\n *\n * `cadences` takes one voicing per chord and gives each pair its own two, so\n * this entry takes that same array rather than a shape only it understands: a\n * caller holding what `voice()` returned can hand it to either method. A\n * two-element array is the closing pair already, which is what a progression\n * of two chords produces either way.\n */\n #closingVoicing(voicing: number[][]): [number[], number[]] {\n if (voicing.length === this.#chords.length || voicing.length === 2) {\n return [voicing[voicing.length - 2] ?? [], voicing[voicing.length - 1] ?? []];\n }\n // Splitting the first two off a mismatched array would grade the cadence on\n // the wrong chords and report nothing about it.\n throw new InvalidInputError(\n `voicing must hold one voicing per chord (${this.#chords.length}) or the closing pair; received ${voicing.length}`,\n );\n }\n\n /**\n * Choose one compatible scale for every chord, favoring smooth changes.\n *\n * @returns One scale choice per chord in this progression.\n */\n scales(): ScaleChoice[] {\n return scalesForChanges(this.#chords.map((chord) => chord.data));\n }\n\n /**\n * Classify the motion at every chord change, not only the closing one.\n *\n * One entry per adjacent pair, so entry `i` is the motion from chord `i` to\n * chord `i + 1` and the list is one shorter than the progression. A pair that\n * cadences not at all keeps its place with a null `type`, which is what lets a\n * caller read a cadence back against the chord it arrives on — a progression\n * has no beats to name it by.\n *\n * The chord before each pair is supplied from the progression itself, so a\n * cadential six-four is recognized as one wherever it stands.\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @param opts `voicing` is the pitches sounding under the whole progression,\n * one voicing per chord as {@link Progression.voice} produces them, from\n * which each pair takes its own two — without it no authentic cadence can be\n * graded perfect or imperfect. `alternatives` collects the readings each\n * pair came close to, and `approach` is the chord sounding before the\n * progression began, which only the first pair has no predecessor of its\n * own for. See {@link DetectCadenceOptions}, whose fields these are.\n * @returns One cadence per adjacent pair, in order.\n * @throws If no key is given and none is carried.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * const progression = new Progression(\n * [Chord.parse('C'), Chord.parse('F'), Chord.parse('G7'), Chord.parse('C')],\n * Key.major('C'),\n * );\n * progression.cadences().map((cadence) => cadence.type); // [null, 'half', 'authentic']\n * ```\n */\n cadences(\n key?: KeyLike,\n opts?: { voicing?: number[][] } & Pick<DetectCadenceOptions, 'alternatives' | 'approach'>,\n ): CadenceResult[] {\n const resolved = this.#resolveKey(key);\n const found: CadenceResult[] = [];\n for (let index = 1; index < this.#chords.length; index += 1) {\n const from = this.#chords[index - 1];\n const to = this.#chords[index];\n if (from === undefined || to === undefined) {\n continue;\n }\n // The progression supplies its own predecessor wherever it has one; the\n // caller's `approach` is for the first pair, which has none. It is taken\n // in the width the option it mirrors declares, so a chord named as a\n // symbol reaches the detector rather than being read for a field only the\n // class shape has and arriving as undefined.\n const approach = index >= 2 ? this.#chords[index - 2]?.data : opts?.approach;\n const pair = opts?.voicing;\n found.push(\n detectCadence(from.data, to.data, resolved, {\n ...(opts?.alternatives === undefined ? {} : { alternatives: opts.alternatives }),\n ...(approach === undefined ? {} : { approach }),\n ...(pair === undefined\n ? {}\n : { voicing: [pair[index - 1] ?? [], pair[index] ?? []] as [number[], number[]] }),\n }),\n );\n }\n return found;\n }\n\n /**\n * A copy of this progression with one chord replaced by a substitute.\n *\n * The substitutions are the ones {@link substituteChord} proposes for that\n * chord in this progression's key, and the first of the named kind is taken.\n * Each is spelled the way the key writes it, so the tritone substitute of G7\n * in C major arrives as Db7 rather than C#7.\n *\n * @param index 0-based position of the chord to replace; a negative index\n * counts from the end, as {@link Progression.at} counts it.\n * @param type Which substitution relationship to realize.\n * @param opts `melodyPcs` keeps only substitutes that contain those pitch\n * classes, so a melody stays consonant against the new harmony; see\n * {@link SubstituteOptions}.\n * @returns The progression with the substitute in place.\n * @throws If the index names no chord, if the progression carries no key\n * context, or if that chord has no substitution of the named kind.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * const progression = new Progression([Chord.parse('G7'), Chord.parse('C')], Key.major('C'));\n * progression.substitute(0, 'tritone').toString(); // 'Db7 C'\n * ```\n */\n substitute(index: number, type: SubstitutionType, opts?: SubstituteOptions): Progression {\n const position = index < 0 ? this.#chords.length + index : index;\n const target = this.#chords[position];\n if (target === undefined) {\n throw new InvalidInputError(\n `progression has no chord at index ${index}; it holds ${this.#chords.length}`,\n );\n }\n const key = this.#resolveKey();\n const chosen = substituteChord(target.data, key, opts).find(\n (candidate) => candidate.type === type,\n );\n if (chosen === undefined) {\n throw new InvalidInputError(\n `no ${type} substitution for ${target.symbol()} in ${key.toString()}`,\n );\n }\n const chords = [...this.#chords];\n chords[position] = new ChordClass(chosen.chord);\n return new Progression(chords, key);\n }\n\n /**\n * Place the chords on a regular grid, giving each the same number of beats.\n *\n * The inverse of {@link Timeline.progression}, which drops the time axis\n * again. A carried key becomes the one key region under the span.\n *\n * @param beatsEach How long each chord sounds.\n * @returns The timeline.\n * @throws If `beatsEach` is not a positive finite number of beats.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * const progression = new Progression([Chord.parse('C'), Chord.parse('G7')], Key.major('C'));\n * progression.timeline(4).at(5)?.symbol(); // 'G7'\n * ```\n */\n timeline(beatsEach: number): Timeline {\n return Timeline.fromProgression(this, beatsEach);\n }\n\n /**\n * Transpose every chord by a number of semitones.\n *\n * A carried key moves with the chords, so the progression keeps its degrees\n * and functions in the new key.\n *\n * @param semitones The signed semitone offset.\n * @returns The transposed progression.\n * @example\n * ```ts\n * import { Chord, Progression } from '@libraz/libcantus';\n * new Progression([Chord.parse('C'), Chord.parse('G')]).transpose(2).toString(); // 'D A'\n * ```\n */\n transpose(semitones: number): Progression {\n const key = this.#key?.transpose(semitones);\n // The constructor hands the transposed key to every member, so a chord\n // spelled by this progression's key follows it instead of falling back to\n // sharps in a flat key.\n const chords = this.#chords.map((chord) => chord.transpose(semitones));\n return new Progression(chords, key);\n }\n\n /**\n * Transpose every chord by a spelled interval.\n *\n * Unlike {@link Progression.transpose}, which picks letters from a semitone\n * count, the interval's diatonic number decides them, so a progression taken\n * up an augmented fourth is spelled with sharps and one taken up a diminished\n * fifth with flats. A carried key moves with the chords.\n *\n * @param interval An interval name (e.g. `'A4'`, `'-m3'`), plain interval\n * data, or an {@link Interval}; a descending interval moves down.\n * @returns The transposed progression.\n * @example\n * ```ts\n * import { Chord, Progression } from '@libraz/libcantus';\n * new Progression([Chord.parse('C'), Chord.parse('G7')]).transposeBy('A4').toString();\n * // 'F# C#7'\n * ```\n */\n transposeBy(interval: IntervalLike): Progression {\n const key = this.#key?.transposeBy(interval);\n // The constructor hands the transposed key to every member, so a chord\n // spelled by this progression's key follows it instead of falling back to\n // sharps in a flat key.\n const chords = this.#chords.map((chord) => chord.transposeBy(interval));\n return new Progression(chords, key);\n }\n\n /**\n * Transpose the progression so that its key becomes `target`.\n *\n * The interval between the two tonics moves the chords and decides their\n * spelling, so moving C major to Gb major writes flats while moving it to F#\n * major writes sharps. The result carries `target` itself, mode included: the\n * chords move by interval but the key is replaced rather than transposed, so\n * a target in another mode — a relative, parallel, or modal key — is the key\n * the progression is then analyzed in.\n *\n * @param target The key the transposed progression should be in, as a key\n * name, a plain key/scale, or a {@link Key}.\n * @returns The transposed progression, carrying `target` as its key.\n * @throws If the progression carries no key context to measure from.\n * @example\n * ```ts\n * import { Chord, Key, Progression } from '@libraz/libcantus';\n * const progression = new Progression([Chord.parse('C'), Chord.parse('G7')], Key.major('C'));\n * progression.transposeTo(Key.major('Eb')).toString(); // 'Eb Bb7'\n * ```\n */\n transposeTo(target: KeyLike): Progression {\n const from = this.#key;\n if (from === undefined) {\n throw new InvalidInputError(\n 'progression has no key context; attach one with withKey() before transposing to another key',\n );\n }\n assertKeyArgument(target, 'progression key');\n const resolved = toKey(target);\n const interval = from.intervalTo(resolved);\n const chords = this.#chords.map((chord) => chord.transposeBy(interval));\n return new Progression(chords, resolved);\n }\n\n /**\n * The chord symbols separated by spaces, so a template literal or a log line\n * reads as the progression.\n *\n * @returns The symbols in order, e.g. `'C Am F G'`.\n */\n toString(): string {\n return this.#chords.map((chord) => chord.symbol()).join(' ');\n }\n\n /**\n * The plain progression data, for JSON serialization.\n *\n * Private class fields do not serialize, so this preserves both the chord\n * data and any carried key in `JSON.stringify(progression)`.\n *\n * @returns The chord data sequence and the carried key, if any.\n */\n toJSON(): ProgressionData {\n return {\n chords: this.#chords.map((chord) => chord.toJSON()),\n key: this.#key?.toJSON(),\n };\n }\n\n /**\n * Resolve the key for an analysis method: explicit first, then carried.\n *\n * Every method that takes a key comes through here, so the shape check and\n * the fallback to the carried context are the same wherever a key is read.\n */\n #resolveKey(key?: KeyLike): Key {\n assertKeyArgument(key, 'progression key');\n const resolved = key === undefined ? this.#key : toKey(key);\n if (resolved === undefined) {\n throw new InvalidInputError(\n 'progression has no key context; pass a Key or attach one with withKey()',\n );\n }\n return resolved;\n }\n}\n","import type { ChordMatch, DetectChordOptions } from '../analyze/detect/index.js';\nimport { detectChord, detectChordBest } from '../analyze/detect/index.js';\nimport {\n type AnalyzeChordOptions,\n analyzeChord,\n type BorrowedSource,\n borrowedSource,\n type ChordAnalysis,\n type ChordToRomanOptions,\n chordToRoman,\n type ExplainRomanOptions,\n explainRoman,\n functionOf,\n type HarmonicFunction,\n isBorrowedChord,\n type RomanExplanation,\n secondaryDominantOf,\n} from '../analyze/functional/index.js';\nimport { InvalidInputError, type ParseResult, unwrapParse } from '../core/errors/index.js';\nimport type {\n IntervalLike,\n Note as NoteData,\n NoteLike,\n NoteNameOptions,\n SpelledInterval,\n} from '../core/pitch/index.js';\nimport {\n noteToPitchClass,\n pitchClassOf,\n toNoteData,\n toSpelledInterval,\n transposeByInterval,\n} from '../core/pitch/index.js';\nimport { assertFiniteNumber } from '../core/validation/index.js';\nimport {\n type BorrowedChord,\n modalInterchangePalette,\n negativeHarmonyMirror,\n type SubstituteOptions,\n type Substitution,\n substituteChord,\n} from '../generate/reharmony/index.js';\nimport {\n assertChordQuality,\n type Chord as ChordData,\n type ChordQuality,\n type ChordSpan,\n type ChordSpec,\n type ChordToneRole,\n chordPitchClasses,\n chordSpecOf,\n chordToneRole,\n chordToneSpellings,\n isChordMember,\n makeChord,\n type PitchSpelling,\n spanFromChord,\n transposeChord,\n} from '../theory/chord/index.js';\nimport {\n type AvailableTensionsOptions,\n type AvoidNotesOptions,\n availableTensions,\n avoidNotes,\n type ChordScaleMatch,\n type ChordScaleReportEntry,\n chordScaleReport,\n chordScales,\n} from '../theory/chordscale/index.js';\nimport { figuredBassOf, realizeFiguredBass } from '../theory/figured-bass/index.js';\nimport type { KeyLike, ScaleNameInput } from '../theory/scale/index.js';\nimport { spellChord, spellChordFromRoot, spellPitchClass } from '../theory/spelling/index.js';\nimport {\n type ChordSymbolOptions,\n formatChordSymbol,\n transposeChordSpellings,\n tryParseChordSymbol,\n} from '../theory/symbol/index.js';\nimport {\n type StyledVoicingOptions,\n type VoicingOptions,\n voiceChord,\n voiceChordStyled,\n} from '../theory/voicing/index.js';\nimport { type Key, toKey } from './key.js';\nimport { Note } from './note.js';\nimport { Progression } from './progression.js';\nimport { assertDataArray, assertDataObject, assertKeyArgument, mod12 } from './shared.js';\n\n/** Whether a spelling hint still names the pitch class it is attached to. */\nfunction hintMatches(hint: PitchSpelling | undefined, pc: number | undefined): boolean {\n return hint !== undefined && pc !== undefined && mod12(noteToPitchClass(hint)) === mod12(pc);\n}\n\n/**\n * Move an explicit spelling hint by a spelled interval.\n *\n * The interval's diatonic number picks the letter, so a C chord taken up an\n * augmented fourth is spelled F# and up a diminished fifth Gb — the distinction\n * a semitone count alone cannot make.\n */\nfunction transposeHintByInterval(\n hint: PitchSpelling | undefined,\n interval: SpelledInterval,\n): PitchSpelling | undefined {\n if (hint === undefined) {\n return undefined;\n }\n const moved = transposeByInterval(hint, interval);\n return { letter: moved.letter, alter: moved.alter };\n}\n\n/**\n * Move a chord's per-tone spelling hints by a spelled interval.\n *\n * Every tone takes the same letter distance, so the distances between them\n * survive: the German sixth's augmented sixth is still five letters above its\n * root afterwards, whichever letters the two of them land on.\n */\nfunction transposeToneHintsByInterval(\n hints: PitchSpelling[] | undefined,\n interval: SpelledInterval,\n): PitchSpelling[] | undefined {\n return hints?.map((hint) => {\n const moved = transposeByInterval(hint, interval);\n return { letter: moved.letter, alter: moved.alter };\n });\n}\n\n/**\n * Defensive copy of a plain chord.\n *\n * The root and bass are reduced to pitch classes by the same helper\n * {@link makeChord} uses, because this is the other way a chord is built: data\n * arriving from a project file or a plugin would otherwise keep a root of 25\n * that every getter reports verbatim and `equals` compares against a 1 it never\n * matches.\n *\n * A quality no chord table names is refused here, with the same error the\n * builders throw, rather than travelling on as a chord whose analysis methods\n * fail on an undefined table row.\n *\n * A bass equal to the root is dropped: that chord is in root position, and\n * keeping the redundant bass would make it compare unequal to the same chord\n * built without one.\n *\n * Enharmonic spelling hints (`rootSpelling`/`bassSpelling`, populated by\n * `parseChordSymbol`, and the per-tone `toneSpellings` an augmented sixth\n * carries) are carried through so a flat-named chord round-trips through the\n * class API — but only while they still name their own pitch class. A stale\n * hint is dropped here rather than passed on, so that everything downstream,\n * including the derived bass spelling, reads a hint it can trust.\n */\nfunction copyChord(data: ChordData): ChordData {\n assertDataObject(data, 'chord data');\n assertChordQuality(data.quality);\n const rootPc = pitchClassOf(data.rootPc);\n const copy: ChordData = {\n rootPc,\n quality: data.quality,\n // Each offset is checked rather than copied blind: a chord holding a NaN\n // interval voices, spells and formats as a chord that looks real, and the\n // failure surfaces wherever the number is finally used.\n intervals: assertDataArray<number>(data.intervals, 'chord intervals').map((interval, index) =>\n assertFiniteNumber(interval, `chord intervals[${index}]`),\n ),\n };\n const bassPc = data.bassPc === undefined ? undefined : pitchClassOf(data.bassPc);\n if (bassPc !== undefined && bassPc !== rootPc) {\n copy.bassPc = bassPc;\n }\n const tones = chordToneSpellings(data);\n if (tones !== undefined) {\n copy.toneSpellings = tones;\n }\n if (hintMatches(data.rootSpelling, data.rootPc) && data.rootSpelling !== undefined) {\n copy.rootSpelling = { letter: data.rootSpelling.letter, alter: data.rootSpelling.alter };\n }\n // The bass spelling is the slash bass's; with no slash bass left there is\n // nothing for it to name.\n if (hintMatches(data.bassSpelling, copy.bassPc) && data.bassSpelling !== undefined) {\n copy.bassSpelling = { letter: data.bassSpelling.letter, alter: data.bassSpelling.alter };\n }\n return copy;\n}\n\n/**\n * Spell the slash bass of a chord whose root spelling is already settled.\n *\n * A bass that is one of the chord's own tones takes that tone's spelling, so\n * `Eb/Bb` never renders as `Eb/A#`; a bass outside the chord is spelled by the\n * key when one is available.\n */\nfunction deriveBassSpelling(chord: ChordData, key: Key | undefined): PitchSpelling | undefined {\n const bassPc = chord.bassPc;\n if (bassPc === undefined) {\n return undefined;\n }\n const root = chord.rootSpelling;\n if (root !== undefined) {\n const index = chord.intervals.findIndex((i) => mod12(chord.rootPc + i) === bassPc);\n const tone = index >= 0 ? spellChordFromRoot(chord, root)[index] : undefined;\n if (tone !== undefined) {\n return { letter: tone.letter, alter: tone.alter };\n }\n }\n if (key === undefined) {\n return undefined;\n }\n const spelled = spellPitchClass(bassPc, key.tonic.data, key);\n return { letter: spelled.letter, alter: spelled.alter };\n}\n\n/**\n * An immutable chord: a root pitch class, quality, interval template, and\n * optional slash bass, optionally carrying a {@link Key} context. Analysis\n * methods (`roman`, `function`, `analyze`, ...) use an explicitly passed key\n * first and fall back to the carried context.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Cmaj7').invert(1).symbol(); // 'Cmaj7/E' (third in the bass)\n * ```\n */\nexport class Chord {\n /** Exactly what the caller supplied: any spelling here is the caller's own. */\n readonly #given: ChordData;\n readonly #key: Key | undefined;\n\n /**\n * Wrap a plain chord object.\n *\n * @param data The chord; it is copied, never retained or mutated.\n * @param key Optional key context for analysis methods, in whatever form the\n * caller holds it: a key name, a plain key/scale, or a {@link Key}.\n */\n constructor(data: ChordData, key?: KeyLike) {\n this.#given = copyChord(data);\n assertKeyArgument(key, 'chord key');\n this.#key = key === undefined ? undefined : toKey(key);\n }\n\n /**\n * The chord data with any missing spelling hint filled in from the key.\n *\n * Derived spellings are computed on read rather than baked in at construction,\n * so re-attaching a different key re-spells the chord instead of carrying the\n * first key's letters forever. A spelling the caller supplied always wins.\n */\n get #data(): ChordData {\n return this.#dataWithKey(this.#key);\n }\n\n /** Build a read view whose missing spellings are derived from `key`. */\n #dataWithKey(key: Key | undefined): ChordData {\n const out = copyChord(this.#given);\n if (out.rootSpelling === undefined && key !== undefined) {\n out.rootSpelling = spellPitchClass(out.rootPc, key.tonic.data, key);\n }\n if (out.bassSpelling === undefined) {\n const bass = deriveBassSpelling(out, key);\n if (bass !== undefined) {\n out.bassSpelling = bass;\n }\n }\n return out;\n }\n\n /**\n * Build a chord from a root and quality.\n *\n * @param root Root as a note name (e.g. `'Eb'`) or a pitch class.\n * @param quality The chord quality.\n * @param bass Optional slash-chord bass, as a note name (e.g. `'Bb'`) or a\n * pitch class. A named bass keeps its own spelling.\n * @returns The chord (without key context).\n */\n static of(root: string | number, quality: ChordQuality, bass?: string | number): Chord {\n const bassNote = typeof bass === 'string' ? Note.parse(bass) : undefined;\n const bassPc = bassNote !== undefined ? bassNote.pitchClass : (bass as number | undefined);\n const rootNote = typeof root === 'string' ? Note.parse(root) : undefined;\n const data = makeChord(\n rootNote !== undefined ? rootNote.pitchClass : (root as number),\n quality,\n bassPc,\n );\n if (rootNote !== undefined) {\n data.rootSpelling = { letter: rootNote.letter, alter: rootNote.alter };\n }\n if (bassNote !== undefined) {\n data.bassSpelling = { letter: bassNote.letter, alter: bassNote.alter };\n }\n return new Chord(data);\n }\n\n /**\n * Wrap an existing plain chord object.\n *\n * @param data The plain chord.\n * @returns The wrapped chord (without key context).\n */\n static fromData(data: ChordData): Chord {\n return new Chord(data);\n }\n\n /**\n * Rebuild a chord from its {@link Chord.toJSON} output.\n *\n * The key context is not serialized, so the result carries none; re-attach\n * one with {@link Chord.withKey}.\n *\n * @param data The serialized chord.\n * @returns The wrapped chord.\n */\n static fromJSON(data: ChordData): Chord {\n return new Chord(data);\n }\n\n /**\n * The chord a figured bass names: a bass note, the figures written under it,\n * and the key that supplies every interval the figures leave unaltered.\n *\n * The inverse of {@link Chord.figuredBass}, and a static because the figures\n * build a chord rather than read one. The result carries the given bass as\n * its slash bass, so an inversion reads as one wherever a bass is measured\n * against a root, and it keeps the letters the figures asked for. A moving\n * figure such as `4-3` yields the chord it resolves into.\n *\n * No key context is attached — the key here decides what the figures mean,\n * not how the chord is later analyzed — so use {@link Chord.withKey} to carry\n * one on.\n *\n * @param bass The bass note, spelled, as a note name, a MIDI number, or a\n * {@link Note}; its octave, if any, is not used.\n * @param figures The figures written under the bass; empty for an unfigured\n * note.\n * @param key The prevailing key; a key name, a plain key/scale, or a\n * {@link Key}.\n * @returns The chord the figures name (without key context).\n * @throws If the figures are malformed or name no chord, if the key is not\n * heptatonic, or if the figures sound a chord no {@link ChordQuality}\n * names.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.fromFiguredBass('B', '6', 'C major').symbol(); // 'G/B'\n * Chord.fromFiguredBass('G', 'n', 'C minor').symbol(); // 'G'\n * ```\n */\n static fromFiguredBass(bass: NoteLike, figures: string, key: KeyLike): Chord {\n // The key travels whole: reducing it here would take the figures of an\n // Ab minor exercise and read them against the G# minor its pitch classes\n // spell back as.\n return new Chord(realizeFiguredBass(toNoteData(bass), figures, key));\n }\n\n /**\n * Parse a lead-sheet chord symbol (e.g. `'Cmaj7'`, `'F#m7b5'`, `'C/G'`).\n *\n * A symbol is English unless a system is asked for: unlike {@link Key.parse},\n * which reads the notation system off the name, `'B'` here is always the B\n * natural until `'german'` says otherwise.\n *\n * @param symbol The chord symbol.\n * @param opts `system` reads the root and bass in that notation system\n * instead of English.\n * @returns The chord (without key context).\n * @throws If the root or quality is not recognized. Use\n * {@link Chord.tryParse} where failure is ordinary, such as a chord field\n * read on every keystroke.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('H7', { system: 'german' }).symbol(); // 'B7'\n * ```\n */\n static parse(symbol: string, opts?: NoteNameOptions): Chord {\n return unwrapParse(Chord.tryParse(symbol, opts));\n }\n\n /**\n * Parse a lead-sheet chord symbol, reporting failure instead of throwing it.\n *\n * The same reading as {@link Chord.parse}, for the callers where a symbol\n * that does not parse yet is the normal state of the input rather than a\n * fault: a chord field can show what is wrong with what has been typed so far\n * without a `try` around every keystroke.\n *\n * @param symbol The chord symbol.\n * @param opts `system` reads the root and bass in that notation system\n * instead of English.\n * @returns The chord (without key context), or the error explaining why the\n * text is not one.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * const result = Chord.tryParse('Cmaj7(#11)');\n * result.ok ? result.value.symbol() : result.error.message; // 'Cmaj7#11'\n * ```\n */\n static tryParse(symbol: string, opts?: NoteNameOptions): ParseResult<Chord> {\n const parsed = tryParseChordSymbol(symbol, opts);\n return parsed.ok ? { ok: true, value: new Chord(parsed.value) } : parsed;\n }\n\n /**\n * Identify the chords matching a set of pitches, best interpretation first.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @param opts How to interpret the input; see {@link DetectChordOptions}.\n * @returns Ranked chord interpretations (may be empty).\n */\n static detect(pitches: readonly number[], opts?: DetectChordOptions): Chord[] {\n return detectChord(pitches, opts).map(\n (match) => new Chord(makeChord(match.rootPc, match.quality, match.bassPc)),\n );\n }\n\n /**\n * Identify the chords matching a set of pitches, keeping each match's\n * recognition metadata beside the chord.\n *\n * {@link Chord.detect} discards the confidence signals a recognition UI needs\n * — whether the set matched exactly, which chord tones were missing, which\n * input notes were foreign, and which inversion the bass implies.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @param opts How to interpret the input; see {@link DetectChordOptions}.\n * @returns Ranked interpretations, each with its chord and its match record.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * const [best] = Chord.detectMatches([60, 64, 67]);\n * best?.match.exact; // true\n * ```\n */\n static detectMatches(\n pitches: readonly number[],\n opts?: DetectChordOptions,\n ): { chord: Chord; match: ChordMatch }[] {\n return detectChord(pitches, opts).map((match) => ({\n chord: new Chord(makeChord(match.rootPc, match.quality, match.bassPc)),\n match,\n }));\n }\n\n /**\n * The single best chord interpretation of a pitch set.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @param opts How to interpret the input; see {@link DetectChordOptions}.\n * @returns The top-ranked chord, or null when nothing matches.\n */\n static detectBest(pitches: readonly number[], opts?: DetectChordOptions): Chord | null {\n const best = detectChordBest(pitches, opts);\n return best === null ? null : new Chord(best);\n }\n\n /** The root pitch class (0..11). */\n get rootPc(): number {\n return this.#data.rootPc;\n }\n\n /** The chord quality. */\n get quality(): ChordQuality {\n return this.#data.quality;\n }\n\n /** A copy of the semitone offsets above the root. */\n get intervals(): number[] {\n return [...this.#data.intervals];\n }\n\n /** The slash-chord bass pitch class, or undefined in root position. */\n get bassPc(): number | undefined {\n return this.#data.bassPc;\n }\n\n /**\n * A copy of the underlying plain chord object, including the spellings\n * derived from any attached key.\n */\n get data(): ChordData {\n return this.#data;\n }\n\n /**\n * The chord read structurally: the triad it is built on, its seventh, and the\n * alterations, additions and omissions on top of them.\n *\n * The reading comes from the tones themselves, so a chord no symbol names —\n * a detected pitch set, a custom interval template — still describes itself;\n * only a template with no structural reading at all falls back to the one its\n * quality names.\n *\n * @throws If the chord's template has no reading and its quality is unknown.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Cmaj7').spec.base; // 'maj'\n * Chord.parse('C/E').spec.bassPc; // 4\n * ```\n */\n get spec(): ChordSpec {\n return chordSpecOf(this.#data);\n }\n\n /** The carried key context, if any. */\n get key(): Key | undefined {\n return this.#key;\n }\n\n /**\n * A copy of this chord carrying the given key context.\n *\n * Only a spelling the caller supplied (via `Chord.parse`, `Chord.of` with a\n * named root, or plain data carrying a hint) survives; a spelling that came\n * from a previously attached key is re-derived, so re-keying a progression\n * during a modulation does not keep the old key's letters and the order of\n * `withKey` calls does not affect the result.\n *\n * @param key The key context to attach; a key name, a plain key/scale, or a\n * {@link Key}.\n * @returns The new chord.\n */\n withKey(key: KeyLike): Chord {\n return new Chord(this.#given, key);\n }\n\n /**\n * The chord's sorted, deduplicated pitch classes.\n *\n * A slash bass is one of them, because the chord sounds it.\n *\n * @param opts Set `includeBass: false` to enumerate the interval template\n * alone, leaving a slash bass out.\n * @returns Pitch classes ascending in [0, 11].\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('F/G').pitchClasses(); // [0, 5, 7, 9]\n * Chord.parse('F/G').pitchClasses({ includeBass: false }); // [0, 5, 9]\n * ```\n */\n pitchClasses(opts?: { includeBass?: boolean }): number[] {\n return chordPitchClasses(this.#data, opts);\n }\n\n /**\n * Whether a pitch is one of the chord's tones, ignoring octave.\n *\n * A slash bass counts, as it does in {@link Chord.pitchClasses}: the chord\n * sounds it.\n *\n * @param pitch A MIDI pitch or a bare pitch class.\n * @returns True when the pitch class belongs to the chord.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Cmaj7').contains(64); // true\n * Chord.parse('Cmaj7').contains(62); // false\n * ```\n */\n contains(pitch: number): boolean {\n return isChordMember(pitch, this.#data);\n }\n\n /**\n * A pitch's harmonic role in the chord: root, third, fifth, sixth, or\n * seventh.\n *\n * The role follows the pitch's interval above the root, so it answers for the\n * chord's own template rather than for the interval alone: the diminished\n * fifth of a half-diminished seventh is its fifth, while the same interval\n * over a chord that already has a perfect fifth is a `#11` tension and has no\n * basic role.\n *\n * @param pitch A MIDI pitch or a bare pitch class.\n * @returns The chord-tone role, or null when the pitch is a tension or a\n * foreign note.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Cmaj7').roleOf(67); // 'fifth'\n * Chord.parse('Cmaj7').roleOf(62); // null\n * ```\n */\n roleOf(pitch: number): ChordToneRole | null {\n return chordToneRole(pitch, this.#data);\n }\n\n /**\n * The chord's Roman numeral in a key.\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @param opts Applied-numeral rendering options.\n * @returns The Roman numeral string.\n * @throws If no key is given and none is carried.\n */\n roman(key?: KeyLike, opts?: ChordToRomanOptions): string {\n return chordToRoman(this.#data, this.#resolveKey(key), opts);\n }\n\n /**\n * The chord's Roman numeral together with the reasoning behind it: the degree\n * its root was read as, the quality that set the numeral's case and suffix,\n * and what became of the bass.\n *\n * The numeral is exactly the one {@link Chord.roman} gives for the same\n * arguments, so this is that method with its rationale attached — for\n * teaching material, and for any interface whose users argue with the\n * analysis. Ask for `alternatives` to see the numerals the other option\n * settings would have rendered, and why this one was rendered instead.\n *\n * @param key Key to analyze in; a key name, a plain key/scale, or a\n * {@link Key}. Falls back to the carried context.\n * @param opts The rendering options {@link Chord.roman} takes, plus\n * `alternatives` to collect the readings this one turned down; see\n * {@link ExplainRomanOptions}.\n * @returns The numeral, its rationale, and the rejected readings.\n * @throws If no key is given and none is carried.\n * @example\n * ```ts\n * import { Chord, Key } from '@libraz/libcantus';\n * Chord.parse('G7').explain(Key.major('C')).roman; // 'V7'\n * Chord.parse('D7').explain('C major', { alternatives: true }).alternatives.length;\n * ```\n */\n explain(key?: KeyLike, opts?: ExplainRomanOptions): RomanExplanation {\n return explainRoman(this.#data, this.#resolveKey(key), opts);\n }\n\n /**\n * The chord's harmonic function (tonic / subdominant / dominant) in a key.\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @returns The harmonic function.\n * @throws If no key is given and none is carried.\n */\n function(key?: KeyLike): HarmonicFunction {\n return functionOf(this.#data, this.#resolveKey(key));\n }\n\n /**\n * Full functional analysis: function, borrowing, Roman numeral, and the\n * rationale behind them.\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @param opts Applied-numeral rendering options, plus `alternatives` to\n * collect the readings this analysis turned down; see\n * {@link AnalyzeChordOptions}.\n * @returns The chord analysis.\n * @throws If no key is given and none is carried.\n * @example\n * ```ts\n * import { Chord, Key } from '@libraz/libcantus';\n * Chord.parse('D7').analyze(Key.major('C'), { alternatives: true }).alternatives.length;\n * ```\n */\n analyze(key?: KeyLike, opts?: AnalyzeChordOptions): ChordAnalysis {\n return analyzeChord(this.#data, this.#resolveKey(key), opts);\n }\n\n /**\n * Whether the chord is borrowed from the parallel mode (modal interchange).\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @returns True if the chord is borrowed.\n * @throws If no key is given and none is carried.\n */\n isBorrowed(key?: KeyLike): boolean {\n return isBorrowedChord(this.#data, this.#resolveKey(key));\n }\n\n /**\n * The origin of a non-diatonic chord (parallel mode or Neapolitan), or null.\n *\n * @param key Key to analyze in, as a key name, a plain key/scale, or a\n * {@link Key}; falls back to the carried context.\n * @returns The borrowing source, or null.\n * @throws If no key is given and none is carried.\n */\n borrowedSource(key?: KeyLike): BorrowedSource {\n return borrowedSource(this.#data, this.#resolveKey(key));\n }\n\n /**\n * The chord written as the figures a bass would carry under it: `6`, `64`,\n * `7`, `65`, `43`, `42`, or nothing at all for a root-position triad, with an\n * accidental on any interval the key does not already give.\n *\n * The bass the figures are measured above is the chord's own slash bass, or\n * its root in root position.\n *\n * @param key Key deciding which intervals need no accidental; a key name, a\n * plain key/scale, or a {@link Key}. Falls back to the carried context.\n * @returns The figures, as `realizeFiguredBass` reads them.\n * @throws If no key is given and none is carried, if the key is not\n * heptatonic, or if no figure names the chord — its bass is not one of its\n * tones, its tones do not stack in diatonic thirds above that bass, or it\n * is an added-tone or extended chord the notation has no abbreviation for.\n * @example\n * ```ts\n * import { Chord, Key } from '@libraz/libcantus';\n * Chord.parse('G/B').figuredBass(Key.major('C')); // '6'\n * Chord.parse('G7/D').figuredBass('C major'); // '43'\n * ```\n */\n figuredBass(key?: KeyLike): string {\n return figuredBassOf(this.#data, this.#resolveKey(key));\n }\n\n /**\n * The chords that can stand in for this one in a key: its tritone substitute,\n * the diatonic triads a third away that share two of its tones, the\n * parallel-mode chords with its harmonic function, and its chromatic\n * mediants.\n *\n * Each candidate carries the relationship it realizes, its Roman numeral, and\n * its harmonic function in the key.\n *\n * @param key Key the substitution is read in; a key name, a plain key/scale,\n * or a {@link Key}. Falls back to the carried context.\n * @param opts Set `melodyPcs` to the pitch classes a melody holds over this\n * chord, so only substitutions that keep every one of them a chord tone are\n * proposed.\n * @returns The deduplicated candidates; the chords are plain data, spelled\n * the way the key writes them.\n * @throws If no key is given and none is carried.\n * @example\n * ```ts\n * import { Chord, Key } from '@libraz/libcantus';\n * const subs = Chord.parse('G7').withKey(Key.major('C')).substitutions();\n * subs.find((sub) => sub.type === 'tritone')?.chord.rootPc; // 1\n * ```\n */\n substitutions(key?: KeyLike, opts?: SubstituteOptions): Substitution[] {\n return substituteChord(this.#data, this.#resolveKey(key), opts);\n }\n\n /**\n * The modal-interchange palette of the chord's key: the parallel mode's\n * triads that the key itself does not contain, plus the Neapolitan, each with\n * its Roman numeral and its borrowing source.\n *\n * The palette belongs to the key rather than to this chord, so it is the same\n * list for every chord in it; it is reachable here because a chord is where a\n * caller looking for somewhere else to go already is.\n *\n * @param key Key to borrow into; a key name, a plain key/scale, or a\n * {@link Key}. Falls back to the carried context.\n * @returns The borrowed chords, spelled the way the mode they come from\n * writes them.\n * @throws If no key is given and none is carried.\n * @example\n * ```ts\n * import { Chord, formatChordSymbol, Key } from '@libraz/libcantus';\n * const palette = Chord.parse('C').withKey(Key.major('C')).modalInterchange();\n * palette.map((borrowed) => formatChordSymbol(borrowed.chord));\n * // ['Cm', 'Ddim', 'Eb', 'Fm', 'Gm', 'Ab', 'Bb', 'Db']\n * ```\n */\n modalInterchange(key?: KeyLike): BorrowedChord[] {\n return modalInterchangePalette(this.#resolveKey(key));\n }\n\n /**\n * The chord rendered as a lead-sheet symbol (e.g. `'Cmaj7'`, `'F#m7'`, `'C/G'`).\n *\n * @param opts Set `flats: true` to spell the root/bass with flats, or\n * `system` to write them in another notation system.\n * @returns The chord symbol.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Bb7').symbol({ system: 'german' }); // 'B7'\n * ```\n */\n symbol(opts?: ChordSymbolOptions): string {\n return formatChordSymbol(this.#data, opts);\n }\n\n /**\n * Realize the chord as one MIDI pitch per voice, ascending.\n *\n * A chord that carries a key passes it to the voicer, so the leading tone is\n * not doubled; an explicit `opts.key` overrides it.\n *\n * @param opts Voicing options; defaults to four SATB voices.\n * @returns MIDI pitches, ascending, one per voice.\n * @throws If no voicing fits the given ranges.\n */\n voice(opts?: VoicingOptions): number[] {\n // The carried key travels whole, as it does through the analysis methods:\n // the voicer spells the chord it scores, and its pitch classes alone would\n // have an Ab minor led by the sharps of a G# minor.\n const key = opts?.key ?? this.#key;\n return voiceChord(this.#data, key === undefined ? opts : { ...opts, key });\n }\n\n /**\n * Realize the chord as a single styled voicing (`close`, `drop2`, `drop3`,\n * `shell`, or `rootless`), optionally constraining the top voice.\n *\n * @param opts Styled-voicing options; defaults to a close-position voicing.\n * @returns MIDI pitches, ascending.\n */\n styledVoicing(opts?: StyledVoicingOptions): number[] {\n return voiceChordStyled(this.#data, opts);\n }\n\n /**\n * The negative-harmony mirror of the chord about the key's tonic–dominant\n * axis (major becomes minor and vice versa).\n *\n * @param key Key providing the reflection axis, as a key name, a plain\n * key/scale, or a {@link Key}; falls back to the carried context.\n * @returns The mirrored chord, keeping any key context.\n * @throws If no key is given and none is carried.\n */\n negativeHarmony(key?: KeyLike): Chord {\n const resolved = this.#resolveKey(key);\n // Retain the key that anchored the reflection (explicit first, then carried)\n // so a later no-arg analysis method still has a key context. The whole key\n // goes to the mirror as well: reducing it to its scale here is what would\n // spell the reflection in an Ab minor with the sharps of a G# minor.\n return new Chord(negativeHarmonyMirror(this.#data, resolved), resolved);\n }\n\n /**\n * The V7 that tonicizes this chord: a dominant seventh a perfect fifth above\n * this chord's root.\n *\n * The target is the chord itself, so no key is involved and a borrowed or\n * chromatic chord gets its dominant as readily as a diatonic one. A root\n * spelling this chord supplied moves with the root, so `Eb` gives `Bb7`.\n *\n * @returns The secondary dominant, keeping any key context.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Eb').secondaryDominant().symbol(); // 'Bb7'\n * ```\n */\n secondaryDominant(): Chord {\n // #given, not #data: only a caller-supplied spelling is transposed, so a\n // spelling the key derived stays derived and follows the attached key.\n return new Chord(secondaryDominantOf(this.#given), this.#key);\n }\n\n /**\n * The n-th inversion: a copy whose bass is the chord tone `n` steps above the\n * root in the interval template (`invert(1)` puts the third in the bass).\n * `n` wraps around the template length; negative values count backwards.\n *\n * `invert(0)` (and any `n` that wraps to it) is root position, so it carries\n * no slash bass and equals the original chord.\n *\n * @param n The inversion number.\n * @returns The inverted chord, keeping any key context.\n * @throws If the chord has no intervals.\n */\n invert(n: number): Chord {\n const data = copyChord(this.#given);\n const intervals = data.intervals;\n const length = intervals.length;\n if (length === 0) {\n throw new InvalidInputError('cannot invert a chord with no intervals');\n }\n const index = ((n % length) + length) % length;\n // The bass spelling follows from the root spelling in force at read time, so\n // it is derived rather than frozen in here.\n delete data.bassSpelling;\n if (index === 0) {\n delete data.bassPc;\n } else {\n data.bassPc = mod12(data.rootPc + (intervals[index] ?? 0));\n }\n return new Chord(data, this.#key);\n }\n\n /**\n * Transpose the chord by a number of semitones.\n *\n * The quality and interval template are carried over, so a chord that a\n * symbol round-trip could not express — a custom interval set, an inversion —\n * survives. A carried key moves with the chord, so the transposed chord keeps\n * the same degree and function inside the transposed key.\n *\n * @param semitones The signed semitone offset.\n * @returns The transposed chord, in the transposed key when one is carried.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('C/G').transpose(2).symbol(); // 'D/A'\n * ```\n */\n transpose(semitones: number): Chord {\n const moved = transposeChord(this.#given, semitones);\n // The spellings are respelled where moving them by letter would name a root\n // no chart writes, the way the symbol module writes a transposed chart and\n // the way a key keeps its own tonic writable.\n const { rootSpelling, bassSpelling, toneSpellings } = transposeChordSpellings(\n this.#given,\n semitones,\n );\n if (rootSpelling !== undefined) {\n moved.rootSpelling = rootSpelling;\n }\n if (bassSpelling !== undefined) {\n moved.bassSpelling = bassSpelling;\n }\n if (toneSpellings !== undefined) {\n moved.toneSpellings = toneSpellings;\n }\n return new Chord(moved, this.#key?.transpose(semitones));\n }\n\n /**\n * Transpose the chord by a spelled interval.\n *\n * Unlike {@link Chord.transpose}, which picks letters from a semitone count,\n * the interval's diatonic number decides them: a C chord up an augmented\n * fourth is F#, up a diminished fifth Gb. As with the semitone form, the\n * quality and interval template are carried over and a carried key moves with\n * the chord.\n *\n * @param interval An interval name (e.g. `'A4'`, `'-m3'`), plain interval\n * data, or an {@link Interval}; a descending interval moves down.\n * @returns The transposed chord, in the transposed key when one is carried.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('C').transposeBy('A4').symbol(); // 'F#'\n * Chord.parse('C').transposeBy('d5').symbol(); // 'Gb'\n * ```\n */\n transposeBy(interval: IntervalLike): Chord {\n const spelled = toSpelledInterval(interval);\n const moved = transposeChord(this.#given, spelled.semitones);\n // #given, not #data: only a caller-supplied spelling is transposed, so a\n // spelling the key derived stays derived and follows the transposed key.\n const rootSpelling = transposeHintByInterval(this.#given.rootSpelling, spelled);\n const bassSpelling = transposeHintByInterval(this.#given.bassSpelling, spelled);\n const toneSpellings = transposeToneHintsByInterval(this.#given.toneSpellings, spelled);\n if (rootSpelling !== undefined) {\n moved.rootSpelling = rootSpelling;\n }\n if (bassSpelling !== undefined) {\n moved.bassSpelling = bassSpelling;\n }\n if (toneSpellings !== undefined) {\n moved.toneSpellings = toneSpellings;\n }\n return new Chord(moved, this.#key?.transposeBy(spelled));\n }\n\n /**\n * The named scales that fit over this chord, best fit first, rooted on the\n * chord root.\n *\n * Only the scales of {@link NAMED_SCALES} are ranked: chord-scale theory is a\n * Western practice, so the scales of {@link WORLD_SCALES} are left out rather\n * than offered as answers over a chord.\n *\n * @returns The matching scales.\n */\n scales(): ChordScaleMatch[] {\n return chordScales(this.#data);\n }\n\n /**\n * The scales that fit over this chord, each with the tones it does not state\n * sorted by what may be done with them: the ones to avoid outright, the ones\n * a line may pass through, and the ones that may be added freely as color.\n *\n * {@link Chord.scales} ranks the same scales in the same order; this is that\n * ranking read as playing advice, so a caller does not have to pair it with\n * {@link Chord.avoidNotes} and {@link Chord.tensions} once per scale.\n *\n * @param limit Greatest number of scales to report; all of them by default.\n * @returns One entry per reported scale, best fit first; see\n * {@link ChordScaleReportEntry}.\n * @throws If `limit` is not a positive integer.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.of('C', 'maj7').scaleReport(1)[0]?.passing; // [5]\n * ```\n */\n scaleReport(limit?: number): ChordScaleReportEntry[] {\n return chordScaleReport(this.#data, limit);\n }\n\n /**\n * The available tensions (usable non-chord, non-avoid scale tones) of a\n * scale over this chord.\n *\n * @param scaleName A scale of {@link NAMED_SCALES}, or one of its aliases,\n * rooted on the chord root. The scales of {@link WORLD_SCALES} are refused\n * here as they are by {@link Chord.scales}: chord-scale theory is a Western\n * practice, and a scale from another tradition offered over a chord would\n * read as an answer while being a category error.\n * @param opts Set `resolvesTo` to the plain chord this one resolves to, so a\n * dominant resolving down a fifth onto a minor tonic takes the tensions\n * that resolution makes available; see {@link AvailableTensionsOptions}.\n * @returns Tension pitch classes, ascending in [0, 11].\n * @throws If `scaleName` is not one of the named scales or their aliases.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.of('G', 'dom7').tensions('phrygianDominant', {\n * resolvesTo: Chord.of('C', 'min').data,\n * }); // [3, 8]\n * ```\n */\n tensions(scaleName: ScaleNameInput, opts?: AvailableTensionsOptions): number[] {\n return availableTensions(this.#data, scaleName, opts);\n }\n\n /**\n * The avoid notes (scale tones a semitone above a chord tone) of a scale\n * over this chord.\n *\n * @param scaleName A scale of {@link NAMED_SCALES}, or one of its aliases,\n * rooted on the chord root. The scales of {@link WORLD_SCALES} are refused\n * here as they are by {@link Chord.scales}: chord-scale theory is a Western\n * practice, and a scale from another tradition offered over a chord would\n * read as an answer while being a category error.\n * @param opts Set `use: 'melodic'` to judge a line rather than a voicing, so\n * a tone a line may pass through is not counted; see\n * {@link AvoidNotesOptions}.\n * @returns Avoid-note pitch classes, ascending in [0, 11].\n * @throws If `scaleName` is not one of the named scales or their aliases.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.of('C', 'maj7').avoidNotes('ionian'); // [5]\n * Chord.of('C', 'maj7').avoidNotes('ionian', { use: 'melodic' }); // []\n * ```\n */\n avoidNotes(scaleName: ScaleNameInput, opts?: AvoidNotesOptions): number[] {\n return avoidNotes(this.#data, scaleName, opts);\n }\n\n /**\n * Spell the chord tones with letter names, root first, in the key's spelling.\n *\n * A chord that already knows how its root is spelled — one from\n * `Chord.parse`, or `Chord.of` with a named root — can spell itself with no\n * key at all; a key is only needed to choose a spelling for a bare pitch\n * class.\n *\n * A slash bass outside the chord tones is appended, so the spelled notes\n * are the notes the chord sounds — the same set {@link Chord.pitchClasses}\n * reports.\n *\n * @param key Key providing the spelled tonic, as a key name, a plain\n * key/scale, or a {@link Key} — the tonic its letters are spelled from is\n * derived from the key rather than asked of the caller. Falls back to the\n * carried context, then to the chord's own root spelling.\n * @returns Spelled octave-less notes in the chord's own (tertian) order,\n * with any foreign slash bass last.\n * @throws If no key is given, none is carried, and the chord has no root\n * spelling of its own.\n */\n spell(key?: KeyLike): Note[] {\n assertKeyArgument(key, 'chord key');\n const resolved = key === undefined ? this.#key : toKey(key);\n // An explicit key must select the spelling view before any derived hints\n // are read; only caller-provided hints in #given are independent of it.\n const data = this.#dataWithKey(resolved);\n let tones: NoteData[];\n if (resolved === undefined) {\n const root = data.rootSpelling;\n if (root === undefined) {\n throw new InvalidInputError(\n 'chord has no key context and no root spelling; pass a Key, attach one with withKey(), or build the chord from a symbol',\n );\n }\n tones = spellChordFromRoot(data, root);\n } else {\n tones = spellChord(data, resolved.tonic.data, resolved);\n }\n const bassPc = data.bassPc;\n const bass = data.bassSpelling;\n if (\n bassPc !== undefined &&\n bass !== undefined &&\n !tones.some((tone) => mod12(noteToPitchClass(tone)) === mod12(bassPc))\n ) {\n tones = [...tones, { letter: bass.letter, alter: bass.alter }];\n }\n return tones.map((note) => new Note(note));\n }\n\n /**\n * Start a progression with this chord followed by others, carrying this\n * chord's key context (if any).\n *\n * @param others The chords following this one.\n * @returns The progression.\n */\n progressionTo(...others: Chord[]): Progression {\n return new Progression([this, ...others], this.#key);\n }\n\n /**\n * The chord placed at a beat, as the {@link ChordSpan} the arrangement and\n * generation functions take.\n *\n * The interval template is recorded only when it departs from the one the\n * quality names, so a standard chord yields the same span it always did while\n * a custom template is not lost. Key context and spelling hints are not part\n * of a span and are left behind.\n *\n * @param startBeat Beat the chord starts on.\n * @returns The span describing this chord at that beat.\n * @throws If `startBeat` is not finite, or the chord's quality is unknown.\n * @example\n * ```ts\n * import { Chord } from '@libraz/libcantus';\n * Chord.parse('Cmaj7').span(4); // { rootPc: 0, quality: 'maj7', startBeat: 4 }\n * ```\n */\n span(startBeat: number): ChordSpan {\n return spanFromChord(this.#data, startBeat);\n }\n\n /**\n * Whether another chord has the same root, quality, intervals, and bass.\n * Key context is not compared.\n *\n * @param other The chord to compare.\n * @returns True if the chord data is identical.\n */\n equals(other: Chord): boolean {\n const a = this.#data;\n const b = other.data;\n return (\n a.rootPc === b.rootPc &&\n a.quality === b.quality &&\n a.bassPc === b.bassPc &&\n a.intervals.length === b.intervals.length &&\n a.intervals.every((interval, i) => interval === b.intervals[i])\n );\n }\n\n /**\n * The plain chord data, for JSON serialization.\n *\n * @returns A copy of the underlying plain chord object.\n */\n toJSON(): ChordData {\n // Key context is intentionally not serialized. Persist only spelling hints\n // the caller provided, so a restored chord can be re-spelled by a new key.\n return copyChord(this.#given);\n }\n\n /**\n * The chord symbol, so a template literal or a log line reads as the chord.\n *\n * @returns The symbol, e.g. `'Cmaj7'`.\n */\n toString(): string {\n return this.symbol();\n }\n\n /**\n * Resolve the key for an analysis method: explicit first, then carried.\n *\n * Every method that takes a key comes through here, so the shape check and\n * the fallback to the carried context are the same wherever a key is read.\n */\n #resolveKey(key?: KeyLike): Key {\n assertKeyArgument(key, 'chord key');\n const resolved = key === undefined ? this.#key : toKey(key);\n if (resolved === undefined) {\n throw new InvalidInputError(\n 'chord has no key context; pass a Key or attach one with withKey()',\n );\n }\n return resolved;\n }\n}\n","import type { DetectKeyOptions, KeyMatch, KeyVariant } from '../analyze/detect/index.js';\nimport { detectKey, detectKeyBest } from '../analyze/detect/index.js';\nimport type { AugmentedSixthKind } from '../analyze/functional/index.js';\nimport {\n augmentedSixthChord,\n isMinorKey,\n pivotChords,\n romanToChord,\n} from '../analyze/functional/index.js';\nimport { InvalidInputError, type ParseResult, unwrapParse } from '../core/errors/index.js';\nimport type {\n IntervalLike,\n Note as NoteData,\n NoteLike,\n NoteNameOptions,\n SpelledInterval,\n} from '../core/pitch/index.js';\nimport {\n formatKeyName,\n spelledInterval,\n toNoteData,\n toSpelledInterval,\n transposeByInterval,\n} from '../core/pitch/index.js';\nimport type { KeyScale } from '../core/types.js';\nimport { assertFiniteNumber, assertInteger, assertOneOf } from '../core/validation/index.js';\nimport {\n type ChordQuality,\n chordFromDegree,\n diatonicSeventh,\n diatonicTriad,\n} from '../theory/chord/index.js';\nimport {\n assertKeyVariant,\n diatonicPitchClasses,\n dominantKeyOf,\n enharmonicKeyOf,\n isScaleTone,\n type KeyLike,\n type KeyMode,\n type KeyRelation,\n keyFromFifths,\n keyRelationBetween,\n keySignatureFifths,\n majorKey,\n minorKey,\n NAMED_SCALES,\n nearestScaleTone,\n parallelKeyOf,\n pitchToScaleDegree,\n type ResolvedKey,\n relatedKeysOf,\n relativeKeyOf,\n resolveKey,\n type ScaleName,\n type ScaleNameInput,\n type ScaleSystem,\n scaleByName,\n scaleSystemOf,\n scaleTonesInDegreeOrder,\n spelledKeyOf,\n subdominantKeyOf,\n supportsFunctionalHarmony,\n toKeyScale,\n tryResolveKeyName,\n variantOfMask,\n} from '../theory/scale/index.js';\n// Reached past the barrel deliberately: the reverse lookup from a mask to the\n// word a key prints is how this class writes itself down, not a question the\n// published scale vocabulary answers for a caller.\nimport { scaleNameOfMask } from '../theory/scale/name.js';\n// Read from the module that owns it rather than through the barrel: the\n// predicate is shared with this class, which is not the same as offering it\n// as a function of the public API.\nimport { isWrittenTonic } from '../theory/scale/relations.js';\nimport { spellPitchClasses, spellScale } from '../theory/spelling/index.js';\nimport type { TransposingInstrument } from '../theory/transposition/index.js';\nimport { toWrittenPitch } from '../theory/transposition/index.js';\nimport { Chord } from './chord.js';\nimport { Interval } from './interval.js';\nimport { Note } from './note.js';\nimport { Progression } from './progression.js';\nimport { assertDataObject, assertKeyArgument, mod12 } from './shared.js';\n\n/** A detected key paired with the score and scale form that produced it. */\nexport type DetectedKeyMatch = Omit<KeyMatch, 'key'> & { key: Key };\n\n/**\n * Restate a detection match with the class API's {@link Key} in its key field.\n *\n * The one place a match crosses into the class API, so every detecting member —\n * on `Key` and on `Score` alike — hands back the same record with the same\n * tonic spelling, and the plain match stays reachable through the key's own\n * data.\n *\n * @param match The match as the detector reports it.\n * @returns The same match, with its key wrapped.\n */\nexport function detectedKeyMatch(match: KeyMatch): DetectedKeyMatch {\n // The same spelling the detector's own rationale is written with, so a match\n // never names its tonic one way in `toString()` and another in `rationale`.\n const key: ResolvedKey = { ...resolveKey(match.key), variant: match.variant };\n return { ...match, key: toKey(key) };\n}\n\n/**\n * The plain form of a {@link Key}: the key/scale, the spelled tonic that\n * anchors its letter names, and the scale form it stands in.\n *\n * The same shape the theory layer resolves a key to, so a key crossing between\n * the two carries the same three facts under the same names, and a project file\n * holds what every layer reads.\n */\nexport type KeyData = ResolvedKey;\n\n/**\n * The word a key names its scale with: the mode word for a plain major or minor\n * key, and the built-in scale's own name written as words for everything else.\n *\n * Read from the mask alone, so the word a key prints is a function of the scale\n * it holds rather than of how it was built: a harmonic minor names itself one\n * whether it was detected or asked for by name. Every register a scale can be\n * built from answers, so a key on a scale outside the Western vocabulary names\n * that scale — a ryūkyū key prints as one instead of claiming the two degrees a\n * major key would add to it. A mask no built-in scale names at all has no word\n * of its own and falls back to the mode its third makes it.\n */\nfunction scaleWord(mask: number, isMinor: boolean): string {\n const name = scaleNameOfMask(mask);\n if (name === undefined) {\n return isMinor ? 'minor' : 'major';\n }\n if (name === 'major') {\n return 'major';\n }\n if (name === 'naturalMinor') {\n return 'minor';\n }\n return name.replace(/([a-z0-9])([A-Z])/g, '$1 $2').toLowerCase();\n}\n\n/** How many degrees a scale needs before thirds can be stacked on it. */\nconst HEPTATONIC_DEGREES = 7;\n\n/** The tonic a mode's reference scale is spelled on; C spells both modes plainly. */\nconst REFERENCE_TONIC: NoteData = { letter: 0, alter: 0 };\n\n/**\n * The interval between two tonics. Both are read octave-less, so the answer is\n * the ascending interval within one octave however the notes were built.\n */\nfunction bareInterval(from: Note, to: Note): SpelledInterval {\n return spelledInterval(\n { letter: from.letter, alter: from.alter },\n { letter: to.letter, alter: to.alter },\n );\n}\n\n/**\n * The tonic spelling a key arriving as a bare pitch class is written with.\n *\n * Routed through {@link spelledKeyOf}, the one place that answers this, so the\n * key a caller prints and the key the theory layer spells — a detection\n * rationale, a spelled line, a key region — never name the tonic differently.\n */\nfunction spelledTonicFor(scale: KeyScale): Note {\n return new Note(resolveKey(scale).tonic);\n}\n\n/**\n * An immutable key/scale: a `KeyScale` (root pitch class plus mode mask) paired\n * with a spelled tonic that anchors letter-name spelling. Acts as the factory\n * for key-aware chords.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').chord(5).symbol(); // 'G' (the diatonic triad on scale degree 5)\n * ```\n */\n/**\n * Whether a value is the class API's {@link Note} rather than the plain note\n * data the pitch functions return.\n *\n * Read structurally rather than with `instanceof`: the package ships an ESM and\n * a CommonJS build, so a consumer reaching the two through different conditions\n * holds two `Note` classes, and an identity test would reject its own note.\n */\nfunction isNoteInstance(value: unknown): value is Note {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n const candidate = value as { pitchClass?: unknown; data?: unknown };\n return typeof candidate.pitchClass === 'number' && typeof candidate.data === 'object';\n}\n\n/** Name what arrived where the class API's {@link Note} was expected. */\nfunction describeTonic(value: unknown): string {\n if (value === null || typeof value !== 'object') {\n return String(value);\n }\n const candidate = value as Partial<NoteData>;\n return typeof candidate.letter === 'number' && typeof candidate.alter === 'number'\n ? 'plain note data'\n : 'an object that is not a note';\n}\n\n/**\n * An immutable key/scale: a `KeyScale` (root pitch class plus mode mask) paired\n * with a spelled tonic that anchors letter-name spelling. Acts as the factory\n * for key-aware chords.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').chord(5).symbol(); // 'G' (the diatonic triad on scale degree 5)\n * ```\n */\nexport class Key {\n readonly #scale: KeyScale;\n readonly #tonic: Note;\n readonly #variant: KeyVariant;\n\n /**\n * Wrap a key/scale and its spelled tonic.\n *\n * @param scale The key/scale; its root is normalized to a pitch class.\n * @param tonic The spelled tonic anchoring letter-name spelling.\n * @param variant The scale form. Read from the mask when none is named: a\n * major mask is a major key whoever built it, and a key with no form at all\n * is a state a reader would have to guess about.\n */\n constructor(scale: KeyScale, tonic: Note, variant?: KeyVariant) {\n assertDataObject(scale, 'scale');\n assertInteger(scale.rootPc, 'scale.rootPc');\n assertInteger(scale.modeMask12, 'scale.modeMask12', 1, 0b111111111111);\n if ((scale.modeMask12 & 1) === 0) {\n throw new InvalidInputError('scale.modeMask12 must include the tonic (bit 0)');\n }\n // Named before the pitch class is read: a plain note from the pitch\n // functions has no `pitchClass`, so the comparison below would report the\n // mismatch of an `undefined` tonic instead of the type that arrived.\n if (!isNoteInstance(tonic)) {\n throw new InvalidInputError(\n `tonic must be the class API's Note; received ${describeTonic(tonic)}; ` +\n 'wrap plain note data with Note.fromData, or omit the tonic to have one chosen',\n );\n }\n const rootPc = mod12(scale.rootPc);\n if (tonic.pitchClass !== rootPc) {\n throw new InvalidInputError(\n `tonic ${tonic.name} does not match the scale root pitch class ${rootPc}; ` +\n 'pass a tonic that spells the scale root, or omit it to have one chosen',\n );\n }\n if (variant !== undefined) {\n assertKeyVariant(variant, scale.modeMask12);\n }\n this.#scale = { rootPc, modeMask12: scale.modeMask12 };\n this.#tonic = tonic;\n this.#variant = variant ?? variantOfMask(scale.modeMask12);\n }\n\n /** Preserve detection metadata while replacing its plain key with this API's Key. */\n static #fromMatch(match: KeyMatch): DetectedKeyMatch {\n return detectedKeyMatch(match);\n }\n\n /**\n * Wrap a key the theory layer spelled, keeping its tonic exactly as given.\n *\n * The relation functions work in fifths space, so the tonic they hand back is\n * already the one the key is written with; re-deriving it from the pitch class\n * would throw that spelling away (Bb minor would come back as A# minor).\n */\n static #fromSpelled(spelled: ResolvedKey): Key {\n return new Key(spelled.scale, new Note(spelled.tonic), spelled.variant);\n }\n\n /**\n * A major key.\n *\n * @param root Tonic as a note name (e.g. `'Eb'`) or a pitch class; a numeric\n * root is spelled the way {@link spelledKeyOf} spells it — the side the\n * scale reads best from, which for a major key is the shorter signature.\n * @returns The major key.\n */\n static major(root: string | number): Key {\n if (typeof root === 'string') {\n const tonic = Note.parse(root);\n return new Key(majorKey(tonic.pitchClass), tonic);\n }\n const scale = majorKey(root);\n return new Key(scale, spelledTonicFor(scale));\n }\n\n /**\n * A natural-minor key.\n *\n * @param root Tonic as a note name or a pitch class; a numeric root is\n * spelled the way {@link spelledKeyOf} spells it, so pitch class 8 is G#\n * minor and not Ab minor.\n * @returns The minor key.\n */\n static minor(root: string | number): Key {\n if (typeof root === 'string') {\n const tonic = Note.parse(root);\n return new Key(minorKey(tonic.pitchClass), tonic);\n }\n const scale = minorKey(root);\n return new Key(scale, spelledTonicFor(scale));\n }\n\n /**\n * A key on a named scale (e.g. `'dorian'`, `'harmonicMinor'`).\n *\n * @param name The scale name, a key of the scale module's named-scale table.\n * @param root Tonic as a note name or a pitch class; a numeric root is\n * spelled the way {@link spelledKeyOf} spells it, exactly as\n * {@link Key.major} does — pitch class 1 altered is C#, not Db.\n * @returns The key.\n * @throws If the name is not a known scale.\n */\n static named(name: ScaleNameInput, root: string | number): Key {\n if (typeof root === 'string') {\n const tonic = Note.parse(root);\n return new Key(scaleByName(name, tonic.pitchClass), tonic);\n }\n const scale = scaleByName(name, mod12(root));\n return new Key(scale, spelledTonicFor(scale));\n }\n\n /**\n * Parse a key name, in any of the supported note-name systems.\n *\n * The name is a tonic and a mode word — `'C major'`, `'gis moll'`,\n * `'嬰ト短調'`, `'la minore'` — and the system is detected from the name\n * itself unless one is given. A German name may also be written with a\n * hyphen (`'gis-Moll'`), and its case carries the mode on its own, so `'Gis'`\n * is G sharp major and `'gis'` G sharp minor; see {@link parseKeyName} for\n * how a name whose case and mode word disagree is read.\n *\n * An English name may also name a built-in scale instead of a mode —\n * `'D harmonic minor'`, `'D dorian'`, `'C major pentatonic'` — which is what\n * {@link Key.toString} writes for a key that is neither a plain major nor a\n * plain minor, so a key survives being written down and read back. Only the\n * tonic's spelling survives from the name, so `'ges dur'` is G flat major,\n * not F sharp major.\n *\n * @param text The key name.\n * @param opts `system` reads the name in that notation system instead of\n * detecting it.\n * @returns The key.\n * @throws If the text is not a key name in the given (or detected) system,\n * or if it mixes two systems.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.parse('gis moll').toString(); // 'G# minor'\n * Key.parse('B dur').toString(); // 'Bb major' — the German B is a B flat\n * Key.parse('B major').toString(); // 'B major'\n * ```\n */\n static parse(text: string, opts?: NoteNameOptions): Key {\n return unwrapParse(Key.tryParse(text, opts));\n }\n\n /**\n * Parse a key name, reporting failure instead of throwing it.\n *\n * The same reading as {@link Key.parse}, for the callers where text that does\n * not name a key yet is the normal state of the input rather than a fault: a\n * key-signature field can say what is wrong with what has been typed so far\n * without a `try` around every keystroke.\n *\n * @param text The key name.\n * @param opts `system` reads the name in that notation system instead of\n * detecting it.\n * @returns The key, or the error explaining why the text is not one.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * const result = Key.tryParse('gis moll');\n * result.ok ? result.value.toString() : result.error.message; // 'G# minor'\n * ```\n */\n static tryParse(text: string, opts?: NoteNameOptions): ParseResult<Key> {\n // The whole reading lives in the theory layer, so a name handed to a\n // function that takes a `KeyLike` and a name handed to this class are the\n // same name: the scale words, the notation systems and the spelling the\n // text carries are one vocabulary rather than two that drift.\n const parsed = tryResolveKeyName(text, opts);\n return parsed.ok\n ? {\n ok: true,\n value: new Key(parsed.value.scale, new Note(parsed.value.tonic), parsed.value.variant),\n }\n : parsed;\n }\n\n /**\n * The key a key signature denotes: the inverse of {@link Key.fifths}.\n *\n * A signature names two keys — three sharps is both A major and F# minor — so\n * the mode decides which one is built. The tonic is spelled the way that key\n * is written, including the theoretical keys past ±7 (nine sharps is D#\n * major).\n *\n * @param fifths The signed number of sharps (positive) or flats (negative).\n * @param mode Which of the signature's two keys to build; defaults to major.\n * @returns The key.\n * @throws If `fifths` is not an integer in [-12, 12], or `mode` is neither\n * `'major'` nor `'minor'`.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.fromFifths(-2).toString(); // 'Bb major'\n * Key.fromFifths(-2, 'minor').toString(); // 'G minor'\n * ```\n */\n static fromFifths(fifths: number, mode: KeyMode = 'major'): Key {\n return Key.#fromSpelled(keyFromFifths(fifths, mode));\n }\n\n /**\n * Wrap an existing `KeyScale`, synthesizing a spelled tonic when none is\n * given.\n *\n * The synthesized tonic is chosen the same way as for a numeric root\n * elsewhere, by {@link spelledKeyOf}: the side the scale reads best from.\n * This is what keeps `Key.of(detectKey(...).scale)` from handing every\n * downstream chord a double-sharp spelling.\n *\n * A value that already carries a spelling keeps it — a key region's key, the\n * data a key serializes to — so wrapping one is not where an Ab minor becomes\n * a G# minor. Only a bare key/scale has a tonic chosen for it, because only a\n * bare key/scale is missing one.\n *\n * @param key The key to wrap, in any form a key is held in.\n * @param tonic Optional spelled tonic, overriding any the value carries; must\n * spell the scale's root pitch class.\n * @returns The key.\n * @throws If the given tonic is not the scale's root pitch class.\n */\n static of(key: KeyLike, tonic?: Note): Key {\n const resolved = resolveKey(key);\n return new Key(resolved.scale, tonic ?? new Note(resolved.tonic), resolved.variant);\n }\n\n /**\n * Rebuild a key from its {@link Key.toJSON} output.\n *\n * @param data The serialized key, tonic, and scale form.\n * @returns The key.\n */\n static fromJSON(data: KeyData): Key {\n assertDataObject(data, 'key data');\n return new Key(data.scale, new Note(data.tonic), data.variant);\n }\n\n /**\n * Wrap plain key data, matching the `fromData` factory on the other classes.\n *\n * @param data The plain key, as {@link Key.data} hands it out.\n * @returns The key.\n */\n static fromData(data: KeyData): Key {\n return Key.fromJSON(data);\n }\n\n /**\n * Identify the keys a set of pitches fits, best interpretation first.\n *\n * The counterpart of {@link Chord.detect}.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @param opts How to weigh the input; see {@link DetectKeyOptions}.\n * @returns Ranked keys (may be empty).\n */\n static detect(pitches: readonly number[], opts?: DetectKeyOptions): Key[] {\n return Key.detectMatches(pitches, opts).map((match) => match.key);\n }\n\n /**\n * Identify keys while retaining each candidate's score, fit, and scale form.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @param opts How to weigh the input; see {@link DetectKeyOptions}.\n * @returns Ranked key matches (may be empty).\n */\n static detectMatches(pitches: readonly number[], opts?: DetectKeyOptions): DetectedKeyMatch[] {\n return detectKey(pitches, opts).map((match) => Key.#fromMatch(match));\n }\n\n /**\n * The single best key interpretation of a pitch set.\n *\n * @param pitches MIDI pitches or bare pitch classes.\n * @param opts How to weigh the input; see {@link DetectKeyOptions}.\n * @returns The top-ranked key, or null when nothing matches.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.detectBest([0, 2, 4, 5, 7, 9, 11])?.toString(); // 'C major'\n * ```\n */\n static detectBest(pitches: readonly number[], opts?: DetectKeyOptions): Key | null {\n const best = detectKeyBest(pitches, opts);\n return best === null ? null : Key.#fromMatch(best).key;\n }\n\n /**\n * Whether another key has the same tonic pitch class and mode.\n *\n * The spelled tonic is not compared: C# major and Db major are the same key\n * written two ways.\n *\n * @param other The key to compare.\n * @returns True when tonic and mode mask both match.\n */\n equals(other: Key): boolean {\n const scale = other.scale;\n return this.#scale.rootPc === scale.rootPc && this.#scale.modeMask12 === scale.modeMask12;\n }\n\n /** A copy of the underlying plain `KeyScale`. */\n get scale(): KeyScale {\n return { rootPc: this.#scale.rootPc, modeMask12: this.#scale.modeMask12 };\n }\n\n /** The spelled tonic. */\n get tonic(): Note {\n return this.#tonic;\n }\n\n /** The tonic pitch class (0..11). */\n get rootPc(): number {\n return this.#scale.rootPc;\n }\n\n /** Whether the scale has a minor third and no major third. */\n get isMinor(): boolean {\n return isMinorKey(this.#scale);\n }\n\n /**\n * The key signature as a signed count of sharps (positive) or flats\n * (negative) — the `fifths` value a notation format such as MusicXML writes.\n *\n * A scale that is not a diatonic mode takes the signature of its parallel\n * major or minor, so A harmonic minor reports 0: its G# is written as an\n * accidental rather than in the signature.\n *\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('Db').fifths; // -5\n * Key.minor('A').fifths; // 0\n * ```\n */\n get fifths(): number {\n return keySignatureFifths(this.#tonic.data, this.#scale);\n }\n\n /**\n * The built-in scale this key's mode mask is, or undefined when no built-in\n * scale has that mask.\n *\n * Only the Western vocabulary of {@link NAMED_SCALES} answers. A mask cannot\n * say which tradition names it — the major scale, maqam Ajam and thaat Bilaval\n * are the same seven pitch classes — so the scales of {@link WORLD_SCALES} are\n * reached by name rather than read back from one. Where two Western names\n * share a mask the table's own first name answers, so a natural minor reports\n * `'naturalMinor'` rather than `'aeolian'` and a major scale `'major'` rather\n * than `'ionian'`.\n *\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').scaleName; // 'major'\n * Key.minor('A').scaleName; // 'naturalMinor'\n * Key.named('dorian', 'D').scaleName; // 'dorian'\n * ```\n */\n get scaleName(): ScaleName | undefined {\n const mask = this.#scale.modeMask12;\n return (Object.keys(NAMED_SCALES) as ScaleName[]).find((name) => NAMED_SCALES[name] === mask);\n }\n\n /** A copy of the underlying plain key data. */\n get data(): KeyData {\n return this.toJSON();\n }\n\n /** The detected scale form, when this key came from key detection. */\n get variant(): KeyVariant {\n return this.#variant;\n }\n\n /**\n * The scale's pitch classes.\n *\n * They come in scale-degree order by default — the tonic first, then each\n * scale tone above it — so D dorian starts on 2 and wraps past 11 to 0. Ask\n * for `order: 'ascending'` where the answer is a pitch-class set rather than\n * a scale: sorted numerically, it compares directly against what\n * {@link Chord.pitchClasses} reports and against any pitch-class set of the\n * caller's own.\n *\n * @param opts Set `order: 'ascending'` to sort the pitch classes numerically\n * instead of by scale degree.\n * @returns One pitch class per scale degree.\n * @throws If `order` is neither `'degree'` nor `'ascending'`.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.named('dorian', 'D').pitchClasses(); // [2, 4, 5, 7, 9, 11, 0]\n * Key.named('dorian', 'D').pitchClasses({ order: 'ascending' }); // [0, 2, 4, 5, 7, 9, 11]\n * ```\n */\n pitchClasses(opts?: { order?: 'degree' | 'ascending' }): number[] {\n const order =\n opts?.order === undefined\n ? 'degree'\n : assertOneOf(opts.order, ['degree', 'ascending'], 'pitch-class order');\n return order === 'ascending'\n ? diatonicPitchClasses(this.#scale)\n : scaleTonesInDegreeOrder(this.#scale);\n }\n\n /**\n * The kind of pitch organisation this key's scale belongs to: the\n * common-practice material functional harmony is defined on, a modal\n * rotation of it, or a collection that carries no chord function of its own.\n *\n * A key holds a mode mask rather than a tradition, so the mask is read the\n * Western way, exactly as {@link scaleSystemOf} reads a bare `KeyScale`: a\n * key built on maqam Hijaz answers `'modal'`, because those seven pitch\n * classes are also the phrygian dominant. A mask no built-in scale names has\n * no system at all.\n *\n * @returns The scale system, or undefined for a mask that names no built-in\n * scale.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').system(); // 'common-practice'\n * Key.named('dorian', 'D').system(); // 'modal'\n * Key.named('majorPentatonic', 'C').system(); // 'non-functional'\n * ```\n */\n system(): ScaleSystem | undefined {\n return scaleSystemOf(this.#scale);\n }\n\n /**\n * Whether functional (Roman-numeral) analysis describes this key.\n *\n * True for the common-practice and modal systems and false for everything\n * classed as carrying no chord function, so code about to read a pentatonic\n * or a raga as a chord progression can ask here first instead of imposing\n * degrees on it. The mask is read the Western way, as {@link Key.system}\n * reads it.\n *\n * @returns True when functional harmony describes the scale.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.named('harmonicMinor', 'A').supportsFunctionalHarmony(); // true\n * Key.named('majorPentatonic', 'C').supportsFunctionalHarmony(); // false\n * ```\n */\n supportsFunctionalHarmony(): boolean {\n return supportsFunctionalHarmony(this.#scale);\n }\n\n /**\n * The relative key: for a plain major or minor key, the same key signature\n * read in the other mode.\n *\n * Because the new tonic is read off the circle of fifths rather than\n * transposed by semitones, the relative of Db major is Bb minor and not its\n * enharmonic A# minor.\n *\n * A key that is not a plain major or minor is read through the mode its third\n * names and stepped from where its tonic stands on the circle: the relative of\n * D dorian is F major. The shared signature does not carry over to those —\n * D dorian is written with no accidentals and F major with one.\n *\n * @returns The relative key, always a plain major or minor key.\n * @throws If this key's signature falls outside [-12, 12] fifths.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').relative().toString(); // 'A minor'\n * ```\n */\n relative(): Key {\n return Key.#fromSpelled(relativeKeyOf(this.#tonic.data, this.#scale));\n }\n\n /**\n * The parallel key: the other mode on the same tonic, which keeps this key's\n * tonic spelling — the parallel minor of C major is C minor, never B# minor.\n *\n * @returns The parallel key, always a plain major or minor key.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').parallel().toString(); // 'C minor'\n * ```\n */\n parallel(): Key {\n return Key.#fromSpelled(parallelKeyOf(this.#tonic.data, this.#scale));\n }\n\n /**\n * The dominant key: the key a fifth above, in the mode this key's third names.\n *\n * The fifth is measured from the tonic, so a key that is not a plain major or\n * minor answers with the same move: the dominant of D dorian is A minor.\n *\n * @returns The key a fifth above.\n * @throws If the resulting signature falls outside [-12, 12] fifths.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').dominantKey().toString(); // 'G major'\n * ```\n */\n dominantKey(): Key {\n return Key.#fromSpelled(dominantKeyOf(this.#tonic.data, this.#scale));\n }\n\n /**\n * The subdominant key: the key a fifth below, in the mode this key's third\n * names, and the exact inverse of {@link Key.dominantKey} on the tonic\n * spelling.\n *\n * @returns The key a fifth below.\n * @throws If the resulting signature falls outside [-12, 12] fifths.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').subdominantKey().toString(); // 'F major'\n * ```\n */\n subdominantKey(): Key {\n return Key.#fromSpelled(subdominantKeyOf(this.#tonic.data, this.#scale));\n }\n\n /**\n * The same sounding key written the other way round the circle of fifths.\n *\n * Only a spelling within ±7 fifths is offered, because that is as far as keys\n * are actually written: Db major answers with C# major, while C major has no\n * second spelling at all.\n *\n * @returns The other spelling of this key, or null when it has none.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('Db').enharmonic()?.toString(); // 'C# major'\n * Key.major('C').enharmonic(); // null\n * ```\n */\n enharmonic(): Key | null {\n const other = enharmonicKeyOf(this.#tonic.data, this.#scale);\n return other === null ? null : Key.#fromSpelled(other);\n }\n\n /**\n * The six closely related keys, each tagged with its relation.\n *\n * These are the keys the German and Japanese teaching tradition counts as a\n * key's near relations: the relative and parallel keys, the dominant and the\n * subdominant, and the relatives of those two. For a plain major or minor key\n * five of them are written within one accidental of this key's signature — the\n * relative shares it exactly and the other four stand one away; the parallel\n * key stands three away and belongs to the set for the tonic it shares\n * instead.\n *\n * A key that is not a plain major or minor is read through the mode its third\n * names, so its relations are walked from where its tonic stands on the circle\n * rather than from its own signature, and those accidental counts do not\n * describe them.\n *\n * @returns The related keys in relation order.\n * @throws If a neighbouring signature falls outside [-12, 12] fifths.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C')\n * .relatedKeys()\n * .map((related) => `${related.relation}: ${related.key}`);\n * // ['relative: A minor', 'parallel: C minor', 'dominant: G major', ...]\n * ```\n */\n relatedKeys(): { relation: KeyRelation; key: Key }[] {\n return relatedKeysOf(this.#tonic.data, this.#scale).map(({ relation, ...spelled }) => ({\n relation,\n key: Key.#fromSpelled(spelled),\n }));\n }\n\n /**\n * How another key stands to this one.\n *\n * Only the identity test looks at the tonic spelling; every other relation\n * compares tonic pitch class and mode, so C# minor and Db minor both read as\n * the relative of E major. Both keys are read through the mode their third\n * names, so a detected A harmonic minor stands to C major exactly as A minor\n * does, and the answer reads the same from either side.\n *\n * @param other The key the relation is measured to.\n * @returns The relation, or null when `other` is none of this key's related\n * keys.\n * @throws If a neighbouring signature of this key falls outside [-12, 12]\n * fifths.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').relationTo(Key.minor('A')); // 'relative'\n * Key.major('C').relationTo(Key.minor('Eb')); // null\n * ```\n */\n relationTo(other: Key): KeyRelation | null {\n // The other key is read through its public accessors, not its private\n // fields, so a bundle that emits two copies of this class still compares.\n return keyRelationBetween(this.toJSON(), other.toJSON());\n }\n\n /**\n * The chords a modulation from this key into another can pivot on.\n *\n * A pivot belongs to both keys at once, so it is heard as a degree of this\n * key and reinterpreted as a degree of the key being entered. The candidates\n * are this key's diatonic triads, kept when every one of their pitch classes\n * is also a scale tone of `other`; each is reported with its numeral in both\n * keys. A key that stacks no diatonic triads offers nothing to pivot on and\n * yields an empty list rather than an error.\n *\n * @param other The key being entered, as a key name, a plain key/scale, or a\n * {@link Key}.\n * @returns The shared triads, ascending by their degree in this key, each\n * chord carrying this key as its context.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C')\n * .pivotsTo('G major')\n * .map((pivot) => `${pivot.romanFrom}=${pivot.romanTo}`);\n * // ['I=IV', 'iii=vi', 'V=I', 'vi=ii']\n * ```\n */\n pivotsTo(other: KeyLike): { chord: Chord; romanFrom: string; romanTo: string }[] {\n assertKeyArgument(other, 'key');\n return pivotChords(this.#scale, other).map(({ chord, romanFrom, romanTo }) => ({\n chord: new Chord(chord, this),\n romanFrom,\n romanTo,\n }));\n }\n\n /**\n * A scale degree, counted from 1 the way musicians name degrees: `degree(1)`\n * is the tonic and `degree(5)` the dominant.\n *\n * @param n The 1-based scale degree.\n * @returns The spelled note on that degree.\n * @throws If `n` is not an integer within 1..(number of scale degrees) — seven\n * for a diatonic key, five for a pentatonic one.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.minor('A').degree(4).name; // 'D'\n * ```\n */\n degree(n: number): Note {\n const notes = this.notes();\n assertInteger(n, 'degree', 1, notes.length);\n // The bounds check already guarantees the index; the tonic only satisfies\n // the compiler's view of an indexed read.\n return notes[n - 1] ?? this.#tonic;\n }\n\n /**\n * The key rooted on one of this key's scale degrees.\n *\n * Without an explicit `mode` the mode is read off the diatonic triad on that\n * degree: a major triad gives a major key, a minor or diminished one a minor\n * key. So the fourth degree of A minor gives D minor while the fourth degree\n * of C major gives F major. A scale with no diatonic triads — anything that\n * is not heptatonic — falls back to this key's own mode.\n *\n * The tonic is derived rather than given, so the result is respelled to its\n * enharmonic key whenever the letter arithmetic lands past the signatures keys\n * are written with: the fourth degree of a C blues scale reads as F# minor,\n * not as the Gb minor and its nine flats.\n *\n * @param n The 1-based scale degree, as {@link Key.degree} counts them.\n * @param mode The mode of the resulting key; inferred when omitted.\n * @returns The key on that degree.\n * @throws If `n` is outside the scale's degrees.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.minor('A').keyOnDegree(4).toString(); // 'D minor'\n * Key.minor('A').keyOnDegree(4, 'major').toString(); // 'D major'\n * ```\n */\n keyOnDegree(n: number, mode?: KeyMode): Key {\n const tonic = this.degree(n);\n return Key.#modeOn(mode ?? this.#modeOfDegree(n), tonic);\n }\n\n /**\n * The key on whose degree `n` this key's tonic sits: the inverse of\n * {@link Key.keyOnDegree}.\n *\n * D minor is the fourth degree of A minor, so D minor answers A minor here.\n *\n * @param n The 1-based degree this key's tonic should occupy in the result.\n * @param mode The mode of the resulting key; defaults to this key's own mode.\n * @returns The key that has this key's tonic on its `n`th degree.\n * @throws If `n` is not an integer in 1..7 — the result is a major or minor\n * key, which has seven degrees.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.minor('D').keyHavingTonicAsDegree(4).toString(); // 'A minor'\n * ```\n */\n keyHavingTonicAsDegree(n: number, mode?: KeyMode): Key {\n const resolved = mode ?? (this.isMinor ? 'minor' : 'major');\n // The interval from degree 1 to degree n is a property of the mode, not of\n // the tonic, so it is read off the mode's scale built on C and then applied\n // downward to this tonic — which keeps the letter the interval names.\n const reference = spellScale(REFERENCE_TONIC, resolved === 'minor' ? minorKey(0) : majorKey(0));\n assertInteger(n, 'degree', 1, reference.length);\n const first = reference[0] as NoteData;\n const step = spelledInterval(first, reference[n - 1] as NoteData);\n const tonic = new Note(\n transposeByInterval(this.#tonic.data, {\n number: step.number,\n quality: step.quality,\n // Negating a zero span yields -0, which compares unequal to 0.\n semitones: step.semitones === 0 ? 0 : -step.semitones,\n descending: true,\n }),\n );\n return Key.#modeOn(resolved, tonic);\n }\n\n /**\n * A plain major or minor key on a spelled tonic.\n *\n * The tonic is one this class derived — a scale degree of another key — so the\n * result is held to the signatures keys are written with: the fourth degree of\n * a C blues scale is written as an F# minor rather than as the Gb minor its\n * letter arithmetic gives, which would be nine flats.\n */\n static #modeOn(mode: KeyMode, tonic: Note): Key {\n const rootPc = tonic.pitchClass;\n return new Key(mode === 'minor' ? minorKey(rootPc) : majorKey(rootPc), tonic).#asWritten();\n }\n\n /**\n * The mode a scale degree implies, read off its diatonic triad. Scales that\n * have no diatonic triads are tested by their degree count rather than by\n * letting {@link diatonicTriad} throw.\n */\n #modeOfDegree(n: number): KeyMode {\n if (this.pitchClasses().length !== HEPTATONIC_DEGREES) {\n return this.isMinor ? 'minor' : 'major';\n }\n const { quality } = diatonicTriad(n, this.#scale);\n return quality === 'min' || quality === 'dim' ? 'minor' : 'major';\n }\n\n /**\n * Transpose the key by a spelled interval, keeping the spelling the interval\n * names.\n *\n * Unlike {@link Key.transpose}, which picks a letter from the semitone count,\n * the interval's diatonic number decides the tonic's letter: G# minor down an\n * augmented fourth is D minor, while down a diminished fifth it is Dbb minor.\n * The mode mask is unchanged, so the scale keeps its shape.\n *\n * @param interval The interval to apply, as a name (`'A4'`, `'-A4'`), plain\n * interval data, or an {@link Interval}; a descending interval moves down.\n * @returns The transposed key.\n * @throws If the value does not describe a spelled interval.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.minor('D').transposeBy('A4').toString(); // 'G# minor'\n * Key.minor('G#').transposeBy('-A4').toString(); // 'D minor'\n * ```\n */\n transposeBy(interval: IntervalLike): Key {\n const step = toSpelledInterval(interval);\n return new Key(\n { rootPc: mod12(this.#scale.rootPc + step.semitones), modeMask12: this.#scale.modeMask12 },\n new Note(transposeByInterval(this.#tonic.data, step)),\n this.#variant,\n );\n }\n\n /**\n * The spelled interval from this key's tonic to another key's tonic.\n *\n * Both tonics are octave-less, so the interval is measured within one\n * ascending octave: C major to Eb major is a minor third, and Eb major back\n * to C major is a major sixth.\n *\n * @param other The key to measure to.\n * @returns The interval between the two tonics.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').intervalTo(Key.major('F#')).name; // 'A4'\n * ```\n */\n intervalTo(other: Key): Interval {\n return Interval.fromData(bareInterval(this.#tonic, other.tonic));\n }\n\n /**\n * Transpose the key by a number of semitones.\n *\n * The mode mask is unchanged, so the scale keeps its shape; only the tonic\n * moves. The tonic's letter follows the semitone count, and the result is\n * then respelled to its enharmonic key whenever the key would not be written\n * that way: Db major up a semitone reads as D major rather than as Ebb major\n * and its ten flats. A key written with a signature is judged by that\n * signature — anything within ±7 is left exactly as it is, so C major up six\n * semitones stays F# major — and a scale that only borrows one is judged by\n * whether its spelling needs a double accidental. A key whose enharmonic is\n * unwritable too keeps the letter-transposed spelling.\n *\n * Use {@link Key.transposeBy} to transpose by a named interval instead, which\n * spells the tonic exactly as that interval demands.\n *\n * @param semitones The signed semitone offset.\n * @returns The transposed key.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').transpose(2).toString(); // 'D major'\n * Key.major('Db').transpose(1).toString(); // 'D major'\n * ```\n */\n transpose(semitones: number): Key {\n assertFiniteNumber(semitones, 'semitones');\n const rootPc = mod12(this.#scale.rootPc + Math.round(semitones));\n const scale = { rootPc, modeMask12: this.#scale.modeMask12 };\n return new Key(scale, this.#tonic.transpose(semitones), this.#variant).#asWritten();\n }\n\n /**\n * This key respelled to the enharmonic key it would actually be written as,\n * or itself when it is already written that way.\n *\n * What every method that derives a tonic of its own ends on. A derived tonic\n * can land past the signatures music is written with — nine flats, a scale\n * needing double accidentals — and a key nobody would hand a player is not an\n * answer to \"which key is this\". A key the caller spelled is never put through\n * this: only a tonic the library chose is the library's to choose again.\n *\n * The enharmonic key supplies the tonic spelling only: the scale keeps this\n * key's own mask, so a harmonic minor or a pentatonic is respelled rather than\n * flattened into a plain major or minor key. A respelling that does not sound\n * the same root is no respelling at all, so the key stands — deriving a key is\n * total, and no spelling question may turn it into a throw.\n */\n #asWritten(): Key {\n if (this.#isWritten()) {\n return this;\n }\n const other = enharmonicKeyOf(this.#tonic.data, this.#scale);\n const respelled = other === null ? null : new Note(other.tonic);\n return respelled === null || respelled.pitchClass !== mod12(this.#scale.rootPc)\n ? this\n : new Key(this.#scale, respelled, this.#variant);\n }\n\n /**\n * Whether this key is spelled the way keys are actually written, which is\n * what decides whether a key this class derived a tonic for keeps that\n * spelling — {@link Key.transpose}, {@link Key.keyOnDegree} and\n * {@link Key.forInstrument} all end on it.\n *\n * The theory layer owns the answer and this asks it, so the class and the\n * functions name the same written spelling — including at the ends of the\n * church modes, where a window drawn from the major and minor keys and one\n * drawn from the mode itself disagree.\n */\n #isWritten(): boolean {\n return isWrittenTonic(this.#tonic.data, this.#scale);\n }\n\n /**\n * The key a transposing instrument's part is written in, for this key at\n * concert pitch.\n *\n * The direction is written-side: the part is transposed *away* from what the\n * instrument sounds, so a B flat instrument — which sounds a major second\n * lower than it reads — has its part written a major second higher, and a\n * concert C major becomes D major. The tonic is spelled by the interval, so\n * a concert E flat major reads as F major on that instrument rather than as\n * E sharp major, and the mode mask is untouched. What the interval spells is\n * then respelled to its enharmonic key whenever it would not be written that\n * way, since a part is what a player is actually handed: a concert F# major\n * on a B flat clarinet reads as A flat major rather than as a G# major with an\n * F double sharp in its signature.\n *\n * The opposite reading, a written key back to the key it sounds in, is\n * {@link Key.transposeBy} applied to {@link instrumentTransposition} — the\n * instrument's own written-to-sounding interval.\n *\n * @param instrument A built-in instrument name, or an interval naming a\n * transposition the table does not carry.\n * @returns The key the player reads.\n * @throws If the instrument is neither a known name nor a spelled interval.\n * @example\n * ```ts\n * import { Key, instrumentTransposition } from '@libraz/libcantus';\n * Key.major('C').forInstrument('clarinetBb').toString(); // 'D major'\n * Key.major('C').forInstrument('hornF').toString(); // 'G major'\n * Key.major('F#').forInstrument('clarinetBb').toString(); // 'Ab major'\n * // And back: what a part written in C major on a clarinet in A sounds as.\n * Key.major('C').transposeBy(instrumentTransposition('clarinetA')).toString(); // 'A major'\n * ```\n */\n forInstrument(instrument: TransposingInstrument): Key {\n // Routed through the same conversion the notes use, so a key and the notes\n // of its part can never disagree about the direction or the spelling.\n const tonic = new Note(toWrittenPitch(this.#tonic.data, instrument));\n // The part is what a player reads, so the key is held to the signatures\n // parts are written with: a concert F# major on a B flat clarinet is handed\n // over as A flat major and not as the G# major with its F## that the strict\n // interval spelling gives.\n return new Key(\n { rootPc: tonic.pitchClass, modeMask12: this.#scale.modeMask12 },\n tonic,\n this.#variant,\n ).#asWritten();\n }\n\n /**\n * The spelled scale, one note per degree (e.g. C D E F G A B for C major).\n *\n * @returns Spelled octave-less notes in scale-degree order.\n */\n notes(): Note[] {\n return spellScale(this.#tonic.data, this.#scale).map((note) => new Note(note));\n }\n\n /**\n * Alias of {@link Key.notes}.\n *\n * @returns Spelled octave-less notes in scale-degree order.\n */\n spell(): Note[] {\n return this.notes();\n }\n\n /**\n * The spelled scale as note-name strings.\n *\n * @param opts `system` writes the names in that notation system instead of\n * English, matching {@link Key.toString}.\n * @returns One name per scale degree.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').noteNames(); // ['C', 'D', 'E', 'F', 'G', 'A', 'B']\n * Key.minor('G#').noteNames({ system: 'german' })[0]; // 'gis'\n * ```\n */\n noteNames(opts?: NoteNameOptions): string[] {\n return this.notes().map((note) => note.format(opts));\n }\n\n /**\n * Spell arbitrary pitch classes the way this key writes them.\n *\n * The counterpart of {@link Key.notes} for pitches that are not scale\n * degrees: a detected pitch-class set, an analysis result, or a voicing\n * reduced to pitch classes gets the letters and accidentals the key implies,\n * so in F major pitch class 10 reads as Bb while 11 reads as B natural\n * rather than as Cb.\n *\n * Named for what it takes, because {@link Key.spell} already answers the\n * scale itself.\n *\n * @param pcs The pitch classes, spelled in the order they are given.\n * @param tonic Spelled tonic anchoring the letter names, as a note name, a\n * MIDI number, or a {@link Note}; defaults to this key's own tonic. It has\n * to sound this key's root pitch class, so it can only respell that tonic —\n * a Db major key spelled from C#.\n * @returns Spelled octave-less notes, in input order.\n * @throws If `tonic` does not sound this key's root pitch class.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('F')\n * .spellPitchClasses([10, 11])\n * .map((note) => note.name); // ['Bb', 'B']\n * ```\n */\n spellPitchClasses(pcs: readonly number[], tonic?: NoteLike): Note[] {\n const anchor = tonic === undefined ? this.#tonic.data : toNoteData(tonic);\n return spellPitchClasses([...pcs], anchor, this.#scale).map((note) => new Note(note));\n }\n\n /**\n * Build a chord on a scale degree, carrying this key as context.\n *\n * With an explicit quality the quality's interval template is attached to the\n * degree's diatonic root; without one the scale-correct diatonic triad is\n * stacked (e.g. a diminished triad on the leading tone of a major key).\n *\n * @param degree 1-based scale degree of the chord root, as {@link Key.degree}\n * counts them: 1 is the tonic and 5 the dominant.\n * @param quality Optional chord quality.\n * @returns The chord, with this key attached.\n * @throws Without a `quality`, if this key's scale is not heptatonic —\n * stacking thirds needs seven degrees, so the pentatonic, blues,\n * whole-tone, octatonic and chromatic scales have no diatonic triad. Pass\n * an explicit `quality` for those.\n */\n chord(degree: number, quality?: ChordQuality): Chord {\n const data =\n quality === undefined\n ? diatonicTriad(degree, this.#scale)\n : chordFromDegree(degree, quality, this.#scale);\n return new Chord(data, this);\n }\n\n /**\n * The diatonic triad on a scale degree, carrying this key as context.\n *\n * @param degree 1-based scale degree of the chord root, as {@link Key.degree}\n * counts them: 1 is the tonic and 5 the dominant.\n * @returns The triad, with this key attached.\n * @throws If this key's scale is not heptatonic; stacking thirds needs seven\n * degrees. Use {@link Key.chord} with an explicit quality instead.\n */\n diatonicTriad(degree: number): Chord {\n return new Chord(diatonicTriad(degree, this.#scale), this);\n }\n\n /**\n * The diatonic seventh chord on a scale degree, carrying this key as context.\n *\n * @param degree 1-based scale degree of the chord root, as {@link Key.degree}\n * counts them: 1 is the tonic and 5 the dominant.\n * @returns The seventh chord, with this key attached.\n * @throws If this key's scale is not heptatonic; stacking thirds needs seven\n * degrees. Use {@link Key.chord} with an explicit quality instead.\n */\n diatonicSeventh(degree: number): Chord {\n return new Chord(diatonicSeventh(degree, this.#scale), this);\n }\n\n /**\n * Build the chord denoted by a Roman numeral in this key (including applied\n * chords such as `'V7/V'`), carrying this key as context.\n *\n * @param text The Roman numeral.\n * @returns The chord, with this key attached.\n * @throws If the numeral is not valid.\n */\n roman(text: string): Chord {\n // The key goes whole: a numeral naming a chromatic chord is spelled from\n // the tonic, so a bII in Ab minor is built as Bbb rather than as the A its\n // pitch classes read best as.\n return new Chord(romanToChord(text, this), this);\n }\n\n /**\n * The augmented sixth chord of a kind, built in this key.\n *\n * The three kinds share the augmented sixth between the lowered sixth degree\n * and the raised fourth and differ in what fills it: the Italian doubles the\n * tonic, the French adds the second degree, and the German the third. The\n * chord is spelled as the interval demands rather than as its enharmonic\n * dominant seventh, which is what keeps its outward resolution readable.\n *\n * @param kind Which augmented sixth to build.\n * @returns The chord, with this key attached.\n * @throws If the kind names none of the three.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').augmentedSixth('german').rootPc; // 8 (the lowered sixth degree)\n * ```\n */\n augmentedSixth(kind: AugmentedSixthKind): Chord {\n // The whole key, not its pitch classes: the chord is spelled from the tonic\n // this key is written on, so an Ab minor takes the Fb Ab Cb D it is written\n // with rather than the double sharps a G# minor would need.\n return new Chord(augmentedSixthChord(kind, keyIdentity(this)), this);\n }\n\n /**\n * Build a progression from Roman numerals in this key.\n *\n * Each numeral is read as {@link Key.roman} reads it, applied chords included,\n * and the progression carries this key, so it can name its own numerals,\n * functions and cadences without being handed a key again.\n *\n * @param romans The numerals, in order.\n * @returns The progression, carrying this key.\n * @throws If any numeral is not valid.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * const progression = Key.major('C').progression('I', 'vi', 'IV', 'V');\n * progression.toString(); // 'C Am F G'\n * progression.functions(); // ['tonic', 'tonic', 'subdominant', 'dominant']\n * ```\n */\n progression(...romans: string[]): Progression {\n return new Progression(\n romans.map((text) => this.roman(text)),\n this,\n );\n }\n\n /**\n * Whether a pitch belongs to the scale.\n *\n * @param x A MIDI pitch, bare pitch class, or note.\n * @returns True if the pitch class is a scale tone.\n */\n contains(x: number | Note): boolean {\n return isScaleTone(typeof x === 'number' ? x : x.pitchClass, this.#scale);\n }\n\n /**\n * The nearest MIDI pitch whose pitch class is in the scale.\n *\n * The search expands symmetrically outward from `pitch`, and a tie — an equal\n * distance above and below — is settled downward. A pitch already in the scale\n * answers itself.\n *\n * @param pitch The MIDI pitch to snap.\n * @returns The nearest in-scale MIDI pitch.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').nearestTone(61); // 60\n * Key.major('C').nearestTone(64); // 64\n * ```\n */\n nearestTone(pitch: number): number {\n return nearestScaleTone(pitch, this.#scale);\n }\n\n /**\n * The scale degree a pitch sits on, counted from 1: the tonic is degree 1.\n *\n * A pitch outside the scale has no degree and answers null, so a caller\n * reading a degree cannot mistake the absent answer for the tonic.\n *\n * @param pitch A MIDI pitch or a bare pitch class.\n * @returns The 1-based degree, or null when the pitch is not a scale tone.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.major('C').degreeOf(64); // 3\n * Key.major('C').degreeOf(61); // null\n * ```\n */\n degreeOf(pitch: number): number | null {\n const degree = pitchToScaleDegree(pitch, this.#scale);\n return degree === -1 ? null : degree;\n }\n\n /**\n * The plain key data, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(key)` from collapsing to `{}`. The result pairs the\n * `KeyScale` with the spelled tonic and, for a detected harmonic or melodic\n * minor, the scale form — everything {@link Key.fromJSON} needs to rebuild a\n * key that reads and prints as this one.\n *\n * @returns The key/scale, its spelled tonic, and its scale form when it has\n * one.\n */\n toJSON(): KeyData {\n // The variant is omitted rather than written as undefined, so a key that\n // never came from detection serializes to the same object it always did.\n return { scale: this.scale, tonic: this.#tonic.data, variant: this.#variant };\n }\n\n /**\n * The key's tonic and the scale it is read in, so a template literal or a log\n * line reads as the key.\n *\n * The scale word is a function of the scale alone — its root pitch class and\n * mode mask — rather than of how the key was built, so two keys holding the\n * same scale print the same name: a harmonic minor names itself one whether\n * it was detected or asked for by name, and a mode names its mode instead of\n * the major or minor key its third would make it. What is printed is what\n * {@link Key.parse} reads back.\n *\n * A `system` names the key the way that notation system writes it, including\n * German's case convention. The scale word is an English-only qualifier —\n * the other systems have no word for it — so a harmonic minor names its\n * parallel plain minor there.\n *\n * @param opts `system` writes the name in that notation system instead of\n * English.\n * @returns The name, e.g. `'C major'`, `'A minor'` or `'gis moll'`.\n * @example\n * ```ts\n * import { Key } from '@libraz/libcantus';\n * Key.minor('G#').toString(); // 'G# minor'\n * Key.named('dorian', 'D').toString(); // 'D dorian'\n * Key.minor('G#').toString({ system: 'german' }); // 'gis moll'\n * ```\n */\n toString(opts?: NoteNameOptions): string {\n if (opts?.system !== undefined && opts.system !== 'english') {\n return formatKeyName(\n { tonic: this.#tonic.data, mode: this.isMinor ? 'minor' : 'major' },\n opts,\n );\n }\n return `${this.#tonic.name} ${scaleWord(this.#scale.modeMask12, this.isMinor)}`;\n }\n}\n\n/**\n * Resolve any key-shaped value to a {@link Key}.\n *\n * The class API's counterpart to {@link toKeyScale}, and the one place its\n * methods turn a key argument into a key: a name, a plain key/scale and a `Key`\n * all reach the same analysis, spelled the same way, however the caller was\n * holding the key. A name keeps the tonic it was written with, so `'Gb major'`\n * is not handed back as F# major; a bare key/scale is given the tonic\n * {@link spelledKeyOf} chooses for it, which is what lets a method that needs a\n * spelled tonic — `Chord.spell` — derive one instead of demanding it.\n *\n * An instance is read through `toJSON`, never by its type, so a `Key` built by\n * a second copy of the module resolves as its own.\n *\n * @param value A key name, a plain key/scale, or a value whose `toJSON` returns\n * key data.\n * @returns The key.\n * @throws If the value names no key.\n */\nexport function toKey(value: KeyLike): Key {\n if (typeof value === 'string') {\n return Key.parse(value);\n }\n if (typeof value === 'object' && value !== null) {\n const data: unknown =\n 'toJSON' in value && typeof value.toJSON === 'function' ? value.toJSON() : value;\n if (typeof data === 'object' && data !== null) {\n const record = data as Partial<KeyData> & Partial<KeyScale>;\n if (record.scale === undefined) {\n // A flat key/scale may still carry the spelling and the scale form it\n // was named with — that is how a key region hands its key on — so the\n // two are kept where they are there rather than being synthesized.\n const scale = toKeyScale(data as KeyScale);\n return record.tonic === undefined\n ? new Key(scale, spelledTonicFor(scale), record.variant)\n : new Key(scale, new Note(record.tonic), record.variant);\n }\n return record.tonic === undefined\n ? Key.of(toKeyScale(record.scale))\n : Key.fromJSON(record as KeyData);\n }\n }\n throw new InvalidInputError(`key must be a key name or a key/scale; received ${typeof value}`);\n}\n\n/**\n * The plain key/scale that carries a key's identity: its root and mode mask\n * together with the spelled tonic and the scale form it was read under.\n *\n * The counterpart of {@link toKey} for a layer that holds keys as plain\n * key/scales — a key region, a generator's key option — so a key handed down\n * into one and read back out is the key that went in rather than an enharmonic\n * equal of it: an Ab minor comes back Ab minor and not G# minor, and a detected\n * harmonic minor comes back a harmonic minor.\n *\n * @param key The key to write down.\n * @returns The key/scale, its spelled tonic, and its scale form when it has one.\n */\nexport function keyIdentity(key: Key): ResolvedKey {\n return { scale: key.scale, tonic: key.tonic.data, variant: key.variant };\n}\n","import { analyzePolyphony } from '../analyze/arrange/index.js';\nimport type { DetectKeyOptions } from '../analyze/detect/index.js';\nimport { detectKeyFromNotes } from '../analyze/detect/index.js';\nimport type {\n FormSection,\n FormSectionOptions,\n Hypermeter,\n HypermeterOptions,\n Phrase,\n PhraseOptions,\n StructuralCadence,\n} from '../analyze/form/index.js';\nimport {\n hypermeter,\n phrasesFromTimeline,\n sectionsFromNotes,\n structuralCadences,\n} from '../analyze/form/index.js';\nimport type { KeyRegion, KeyTimelineOptions } from '../analyze/keys/index.js';\nimport { keyLookup, keyTimelineFromNotes, prevailingKeyOf } from '../analyze/keys/index.js';\nimport type { ExtractMotifsOptions, MelodicContour, MotifData } from '../analyze/melody/index.js';\nimport { extractMotifs, melodicContour } from '../analyze/melody/index.js';\nimport type {\n ChordTimeline,\n ChordTimelineOptions,\n ChordTimelineResult,\n} from '../analyze/timeline/index.js';\nimport { chordTimelineFromNotes, detectCadences } from '../analyze/timeline/index.js';\nimport type { AnalyzedNote, IdentifiedVoiceNote, KeyContext } from '../analyze/voice/index.js';\nimport { toVoiceNotes } from '../analyze/voice/index.js';\nimport type { NoteEventIndex, NoteEventIndexOptions } from '../core/event-index/index.js';\nimport { createNoteEventIndex } from '../core/event-index/index.js';\nimport type { PlayabilityReport } from '../core/instrument/playability.js';\nimport { playability } from '../core/instrument/playability.js';\nimport type { InstrumentProfile, InstrumentProfileLike } from '../core/instrument/profile.js';\nimport { toInstrumentProfile } from '../core/instrument/profile.js';\nimport type { BarPosition, MeterLike, MeterMap, TimeSignature } from '../core/meter/index.js';\nimport { beatToBarPosition, meterAt, resolveMeters } from '../core/meter/index.js';\nimport type { IntervalLike } from '../core/pitch/index.js';\nimport { toSpelledInterval } from '../core/pitch/index.js';\nimport type { TempoMap } from '../core/tempo/index.js';\nimport {\n beatsToSeconds,\n beatsToTicks,\n tempoAt,\n tempoReader,\n ticksToBeats,\n} from '../core/tempo/index.js';\nimport type { NoteEvent } from '../core/types.js';\nimport { assertFiniteNumber, assertRange } from '../core/validation/index.js';\nimport type { GrooveTemplate, HumanizeOptions, OrnamentOptions } from '../generate/index.js';\nimport {\n applyGrooveTemplate,\n extractGrooveTemplate,\n humanize,\n ornament,\n} from '../generate/index.js';\nimport type { KeyLike } from '../theory/scale/index.js';\nimport { scaleOf } from '../theory/scale/index.js';\nimport type { DetectedKeyMatch, KeyData } from './key.js';\nimport { detectedKeyMatch, Key, keyIdentity, toKey } from './key.js';\nimport {\n assertDataArray,\n assertDataObject,\n assertDataObjects,\n assertKeyArgument,\n assertNoteEventArray,\n copyNoteEvent,\n STATED_KEY_CONFIDENCE,\n withoutNegativeZero,\n} from './shared.js';\nimport { copyKeyRegion, Timeline } from './timeline.js';\n\n/** The plain form a {@link Score} hands out and is rebuilt from. */\nexport type ScoreData = {\n notes: NoteEvent[];\n meters: MeterMap;\n tempo: TempoMap;\n /**\n * The key the notes are read in, when one was given. Absent on a score whose\n * key is left to be inferred, so the two states survive a round trip: a score\n * that carries no key is not one that carries C major.\n */\n key?: KeyData;\n};\n\n/** How a score is built: the notes, plus the context they are read against. */\nexport type ScoreOptions = {\n /** The meter, as one time signature — `'6/8'` or its data — or a map of changes. */\n meters?: MeterLike;\n /** The tempo, as one bpm or a map of changes. */\n tempo?: TempoMap | number;\n /** The key the notes are read in, when it is already known. */\n key?: KeyLike;\n};\n\n/** The tempo a score is read at when the caller names none. */\nconst DEFAULT_BPM = 120;\n\n/**\n * The notes checked and copied, in time order, ties broken by pitch.\n *\n * A score is asked about beats, not about array positions, so the order is\n * settled once here: every method downstream — and every `equals` between two\n * scores holding the same music — then reads the same sequence whatever order\n * the notes arrived in.\n *\n * The array is checked by the shared note-event guard before it is copied, so\n * the count a score keeps is bounded by the same budget the function API bounds\n * it by. Zero-length notes are accepted, as they are everywhere on the analysis\n * side: a MIDI import carries them, and the analyses drop them themselves.\n */\nfunction orderNotes(notes: readonly NoteEvent[], name: string): NoteEvent[] {\n return assertNoteEventArray(notes, name, { allowNonPositiveDuration: true })\n .map((note) => copyNoteEvent(note))\n .sort(\n (a, b) => a.startBeat - b.startBeat || a.pitch - b.pitch || a.durationBeat - b.durationBeat,\n );\n}\n\n/** Defensive copy of a meter map, with its signatures copied entry by entry. */\nfunction copyMeters(meters: MeterMap): MeterMap {\n return assertDataObjects<MeterMap[number]>(meters, 'score meters').map((change) => {\n assertDataObject(change.ts, 'score meters ts');\n const ts: TimeSignature = {\n numerator: change.ts.numerator,\n denominator: change.ts.denominator,\n };\n if (change.ts.grouping !== undefined) {\n ts.grouping = [...change.ts.grouping];\n }\n return { startBeat: withoutNegativeZero(change.startBeat), ts };\n });\n}\n\n/**\n * Defensive copy of a tempo map, validated on the way through.\n *\n * The tempo module keeps its map validator private and runs it from every\n * entry point, so the map is checked by reading the tempo at its own origin:\n * a non-finite bpm, an unsorted entry or an empty map is refused here rather\n * than at the first conversion a caller happens to ask for.\n */\nfunction copyTempo(tempo: TempoMap): TempoMap {\n assertDataObjects<TempoMap[number]>(tempo, 'score tempo');\n tempoAt(0, tempo);\n return tempo.map((event) => ({\n startBeat: withoutNegativeZero(event.startBeat),\n bpm: event.bpm,\n }));\n}\n\n/**\n * Defensive copy of plain score data, with every part validated.\n *\n * This is the boundary a project file, a MIDI import or a hand-edited JSON\n * crosses, so the checks are the library's own: the note events, the meter map\n * and the tempo map are each rejected here if they carry a number the analysis\n * below could not hold.\n */\nfunction copyScore(data: ScoreData): ScoreData {\n assertDataObject(data, 'score data');\n const copy: ScoreData = {\n notes: orderNotes(data.notes, 'score notes'),\n // The map is validated by the same resolver every meter-aware entry point\n // reads its options through, so a score accepts exactly what they accept.\n meters: copyMeters(resolveMeters({ meters: data.meters }, 'score meters')),\n tempo: copyTempo(data.tempo),\n };\n if (data.key !== undefined) {\n copy.key = Key.fromJSON(data.key).toJSON();\n }\n return copy;\n}\n\n/** The tempo map a {@link ScoreOptions.tempo} value names. */\nfunction tempoFrom(tempo: TempoMap | number | undefined): TempoMap {\n if (tempo === undefined) {\n return [{ startBeat: 0, bpm: DEFAULT_BPM }];\n }\n return typeof tempo === 'number' ? [{ startBeat: 0, bpm: tempo }] : tempo;\n}\n\n/**\n * The one region a stated key describes: that key, in force from where the\n * music starts to where the analyzed span ends.\n *\n * The same region the chord analysis builds for a key it was given, so a score\n * that carries a key answers with one key wherever it is asked — from\n * {@link Score.key}, from {@link Score.keys}, and from the timeline it hands\n * out. A score with nothing sounding has no region at all, since there is no\n * music for the key to be in force over.\n */\nfunction statedKeyRegions(key: Key, notes: readonly NoteEvent[], totalBeats: number): KeyRegion[] {\n const first = notes[0];\n if (first === undefined || totalBeats <= first.startBeat) {\n return [];\n }\n return [\n {\n // The region starts where the music does, as an inferred one does, so a\n // pickup is covered by the key it sounds in.\n startBeat: first.startBeat,\n endBeat: totalBeats,\n key: keyIdentity(key),\n confidence: STATED_KEY_CONFIDENCE,\n },\n ];\n}\n\n/** The plain data a set of notes and a context describe. */\nfunction scoreData(notes: readonly NoteEvent[], opts: ScoreOptions | undefined): ScoreData {\n const data: ScoreData = {\n notes: [...assertDataArray<NoteEvent>(notes, 'score notes')],\n meters: resolveMeters({ meters: opts?.meters }, 'score meters'),\n tempo: tempoFrom(opts?.tempo),\n };\n if (opts?.key !== undefined) {\n // Read through the resolver that keeps a spelled tonic and a scale form\n // where the caller had them: a score told its key in Ab minor is not a\n // score in G# minor, and every note it spells afterwards follows.\n data.key = toKey(opts.key).toJSON();\n }\n return data;\n}\n\n/**\n * Sounding notes with the context that gives them meaning: a meter map, a\n * tempo map, and optionally the key they are read in.\n *\n * This is the library's entry point for music that already exists. A DAW\n * plug-in, a transcription tool, or a MIDI importer holds `NoteEvent[]` before\n * it holds anything else, and every question worth asking of it — what chords\n * are these, where do the phrases end, what key is this — took a separate\n * function and a hand-wired chain of intermediate results. A `Score` carries\n * the notes and their context together, so each question is one call and the\n * answers stay in the class API.\n *\n * The notes are held in time order, and their onsets are unbounded below: beat\n * 0 is the first downbeat, so a pickup sounds at a negative beat and is kept\n * there rather than being shifted onto the grid.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Score } from '@libraz/libcantus';\n * const score = Score.of([\n * { pitch: 60, startBeat: 0, durationBeat: 2 },\n * { pitch: 64, startBeat: 0, durationBeat: 2 },\n * { pitch: 67, startBeat: 0, durationBeat: 2 },\n * ]);\n * score.totalBeats; // 2\n * ```\n */\nexport class Score {\n readonly #data: ScoreData;\n readonly #key: Key | undefined;\n /** The chord reading, made on the first member that needs it. */\n #chords: ChordTimelineResult | undefined;\n /** The key regions, made on the first member that needs them. */\n #regions: KeyRegion[] | undefined;\n\n /**\n * Wrap plain score data.\n *\n * @param data The notes and their context; copied, never retained.\n * @throws If a note, the meter map or the tempo map carries a value the\n * analysis cannot hold.\n */\n constructor(data: ScoreData) {\n this.#data = copyScore(data);\n this.#key = this.#data.key === undefined ? undefined : Key.fromJSON(this.#data.key);\n }\n\n /**\n * Build a score from note events.\n *\n * A bare time signature becomes a one-entry meter map taking effect at beat\n * 0, and a bare bpm a one-entry tempo map at beat 0; a score given neither is\n * read in 4/4 at 120 bpm, which is what every meter-aware function in the\n * library assumes when its caller names nothing.\n *\n * @param notes The sounding notes, in any order.\n * @param opts The meter, tempo, and key to read them against.\n * @returns The score.\n * @example\n * ```ts\n * import { Score } from '@libraz/libcantus';\n * const score = Score.of([{ pitch: 60, startBeat: 0, durationBeat: 4 }], {\n * meters: { numerator: 3, denominator: 4 },\n * tempo: 90,\n * });\n * score.meterAt(0).numerator; // 3\n * ```\n */\n static of(notes: readonly NoteEvent[], opts?: ScoreOptions): Score {\n return new Score(scoreData(notes, opts));\n }\n\n /** An empty score, for a track that has not been written yet. */\n static empty(opts?: ScoreOptions): Score {\n return new Score(scoreData([], opts));\n }\n\n /**\n * Read note events whose times are in ticks rather than beats.\n *\n * Onsets and durations are converted; nothing else about the events changes.\n * A negative tick count is a pickup and stays one, since beat 0 is the first\n * downbeat at either resolution.\n *\n * @param events The events, with tick-valued onsets and durations.\n * @param ppq Ticks per quarter note.\n * @param opts The meter, tempo, and key to read them against.\n * @returns The score, in beats.\n * @example\n * ```ts\n * import { Score } from '@libraz/libcantus';\n * const score = Score.fromTicks([{ pitch: 60, startBeat: 480, durationBeat: 960 }], 480);\n * score.notes[0]?.durationBeat; // 2\n * ```\n */\n static fromTicks(events: readonly NoteEvent[], ppq: number, opts?: ScoreOptions): Score {\n const notes = assertDataObjects<NoteEvent>(events, 'score notes').map((event) => ({\n ...event,\n startBeat: ticksToBeats(event.startBeat, ppq),\n durationBeat: ticksToBeats(event.durationBeat, ppq),\n }));\n return new Score(scoreData(notes, opts));\n }\n\n /** Rebuild a score from the plain data {@link Score.data} hands out. */\n static fromData(data: ScoreData): Score {\n return new Score(data);\n }\n\n /** Rebuild a score from its {@link Score.toJSON} output. */\n static fromJSON(data: ScoreData): Score {\n return new Score(data);\n }\n\n /** The sounding notes, in time order. */\n get notes(): readonly NoteEvent[] {\n return this.#data.notes.map(copyNoteEvent);\n }\n\n /**\n * Where the last note stops sounding.\n *\n * Measured from beat 0 rather than from the first onset, so a score that\n * opens with a pickup reports the beat its music ends on and not its length.\n * An empty score ends at 0.\n */\n get totalBeats(): number {\n return this.#data.notes.reduce(\n (end, note) => Math.max(end, note.startBeat + note.durationBeat),\n 0,\n );\n }\n\n /** The meter map the notes are read against. */\n get meters(): MeterMap {\n return copyMeters(this.#data.meters);\n }\n\n /** The tempo map the notes are read against. */\n get tempo(): TempoMap {\n return this.#data.tempo.map((event) => ({ startBeat: event.startBeat, bpm: event.bpm }));\n }\n\n /**\n * The stretch of the score between two beats.\n *\n * A note is kept when its onset falls in `[fromBeat, toBeat)`; the notes keep\n * their absolute onsets, so the slice stays in the score's own time and a\n * slice taken across a meter or tempo change is still read against it.\n *\n * @param fromBeat First beat of the stretch, inclusive.\n * @param toBeat End of the stretch, exclusive.\n * @returns The score holding those notes.\n */\n slice(fromBeat: number, toBeat: number): Score {\n assertFiniteNumber(fromBeat, 'slice fromBeat');\n assertFiniteNumber(toBeat, 'slice toBeat');\n return this.#withNotes(\n this.#data.notes.filter((note) => note.startBeat >= fromBeat && note.startBeat < toBeat),\n );\n }\n\n /** The notes this predicate keeps, with the same context. */\n filter(predicate: (note: NoteEvent, index: number) => boolean): Score {\n return this.#withNotes(\n this.#data.notes.filter((note, index) => predicate(copyNoteEvent(note), index)),\n );\n }\n\n /** The notes this function returns, with the same context. */\n map(fn: (note: NoteEvent, index: number) => NoteEvent): Score {\n return this.#withNotes(this.#data.notes.map((note, index) => fn(copyNoteEvent(note), index)));\n }\n\n /** This score followed by another's notes. */\n concat(other: Score | readonly NoteEvent[]): Score {\n // Read through the public surface rather than by `instanceof`, so a score\n // built by a second copy of the module concatenates like any other.\n const added: readonly NoteEvent[] = Array.isArray(other)\n ? (other as readonly NoteEvent[])\n : (other as Score).notes;\n return this.#withNotes([...this.#data.notes, ...added]);\n }\n\n /**\n * The score moved along the timeline.\n *\n * The meter and tempo maps stay where they are: they describe the bars and\n * the pulse the music is played against, and moving the notes over them is\n * how a phrase is heard a bar later. A negative shift moves music before the\n * first downbeat, which is where a pickup lives.\n *\n * @param beats How far to move, in quarter-note beats; negative moves earlier.\n * @returns The moved score.\n */\n shift(beats: number): Score {\n assertFiniteNumber(beats, 'shift beats');\n return this.#withNotes(\n this.#data.notes.map((note) => ({ ...note, startBeat: note.startBeat + beats })),\n );\n }\n\n /**\n * The score moved by a number of semitones.\n *\n * A carried key moves with the notes, so the score that comes back is read in\n * the key it now sounds in and every analysis taken from it — its timeline,\n * its numerals, its phrases — is taken against that key rather than against\n * the one it was written in.\n *\n * @param semitones The signed semitone offset.\n * @returns The transposed score.\n * @throws If a note would leave the MIDI range.\n */\n transpose(semitones: number): Score {\n assertFiniteNumber(semitones, 'transpose semitones');\n return this.#moved(\n this.#data.notes.map((note) => ({ ...note, pitch: note.pitch + semitones })),\n (key) => key.transpose(semitones),\n );\n }\n\n /**\n * The score moved by a spelled interval, keeping the spelling.\n *\n * Note events carry a MIDI pitch and no spelling of their own, so the\n * interval contributes its size and its direction; a carried key is what\n * keeps the spelling, and it moves with the notes — by the interval itself,\n * so an augmented fourth and a diminished fifth land on differently spelled\n * keys.\n *\n * @param interval An interval name (e.g. `'A4'`, `'-m3'`), plain interval\n * data, or an {@link Interval}; a descending interval moves down.\n * @returns The transposed score.\n */\n transposeBy(interval: IntervalLike): Score {\n const step = toSpelledInterval(interval);\n return this.#moved(\n this.#data.notes.map((note) => ({ ...note, pitch: note.pitch + step.semitones })),\n // Moved by the interval rather than by its semitone count, so a key taken\n // up an augmented fourth and one taken up a diminished fifth are spelled\n // the way each interval demands.\n (key) => key.transposeBy(step),\n );\n }\n\n /** The same notes read against a different meter. */\n withMeters(meters: MeterLike): Score {\n return new Score({ ...this.#data, meters: resolveMeters({ meters }, 'score meters') });\n }\n\n /** The same notes read against a different tempo. */\n withTempo(tempo: TempoMap | number): Score {\n return new Score({ ...this.#data, tempo: tempoFrom(tempo) });\n }\n\n /** The same notes read in a different key. */\n withKey(key: KeyLike): Score {\n return new Score({ ...this.#data, key: toKey(key).toJSON() });\n }\n\n /**\n * The notes pulled onto a grid.\n *\n * Onsets and durations are both snapped to the nearest multiple of the grid,\n * counted from beat 0 in both directions, so a pickup is quantized against\n * the same grid the downbeat is. A duration that would round to nothing keeps\n * one grid unit, since a note quantized out of existence is a note lost.\n *\n * @param grid The grid unit in quarter-note beats (0.25 for sixteenths).\n * @returns The quantized score.\n * @throws If the grid is not a positive length.\n * @example\n * ```ts\n * import { Score } from '@libraz/libcantus';\n * const score = Score.of([{ pitch: 60, startBeat: 0.98, durationBeat: 1.03 }]);\n * score.quantize(0.5).notes[0]?.startBeat; // 1\n * ```\n */\n quantize(grid: number): Score {\n assertRange(grid, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, 'quantize grid');\n return this.#withNotes(\n this.#data.notes.map((note) => ({\n ...note,\n startBeat: Math.round(note.startBeat / grid) * grid,\n durationBeat: Math.max(1, Math.round(note.durationBeat / grid)) * grid,\n })),\n );\n }\n\n /**\n * The notes pushed off the grid the way a player would.\n *\n * The metric accents are read from the score's opening signature, since\n * {@link HumanizeOptions} names one signature rather than a map; pass `ts`\n * to read a later stretch of a score that changes meter.\n *\n * @param opts Jitter amounts, accent depth and the seed; see\n * {@link HumanizeOptions}.\n * @returns The humanized score.\n */\n humanize(opts?: HumanizeOptions): Score {\n return this.#withNotes(humanize(this.#data.notes, { ts: this.meterAt(0), ...opts }));\n }\n\n /**\n * The notes with ornaments added.\n *\n * Strong positions are read from the score's opening signature, since\n * {@link OrnamentOptions} names one signature rather than a map.\n *\n * @param opts The ornament style, how much is decorated, and the seed; see\n * {@link OrnamentOptions}.\n * @returns The ornamented score.\n */\n ornament(opts?: OrnamentOptions): Score {\n return this.#withNotes(ornament(this.#data.notes, { ts: this.meterAt(0), ...opts }));\n }\n\n /**\n * The notes placed on a groove template's slots.\n *\n * The template's per-bar grid is laid out against the score's opening\n * signature, which is the signature the template must have been extracted\n * under; a template carrying a different one is refused rather than drifting.\n *\n * @param template The groove template, from `extractGrooveTemplate`.\n * @returns The score with the template's feel imposed.\n * @throws If the template was extracted under another meter.\n */\n groove(template: GrooveTemplate): Score {\n return this.#withNotes(applyGrooveTemplate(this.#data.notes, template, this.meterAt(0)));\n }\n\n /**\n * The feel of the score's own timing, as a template another score can take on.\n *\n * The other direction of {@link Score.groove}: a played-in take is measured\n * slot by slot for how far ahead of or behind the grid it sits and how hard\n * it is struck, and the reading is handed back as a template. Only the\n * subdivision is named, because the score already holds the meter the grid is\n * laid out against — its opening signature, which is the one the template\n * records and the one an apply-time meter is checked against.\n *\n * @param subdivision Grid steps per quarter-note beat; a sixteenth-note grid\n * by default, which is where swing, push and drag are audible.\n * @returns The template these notes describe.\n * @throws If the subdivision is not a positive whole number.\n * @example\n * ```ts\n * import { Score } from '@libraz/libcantus';\n * const played = Score.of([{ pitch: 36, startBeat: 0.02, durationBeat: 1 }]);\n * Score.of([{ pitch: 36, startBeat: 0, durationBeat: 1 }]).groove(played.grooveTemplate());\n * ```\n */\n grooveTemplate(subdivision?: number): GrooveTemplate {\n return extractGrooveTemplate(this.#data.notes, this.meterAt(0), subdivision);\n }\n\n /**\n * The harmony the notes spell out, in time.\n *\n * The score's meter map and its key, when it carries one, are read against\n * unless the options name others.\n *\n * @param opts Analysis options; see {@link ChordTimelineOptions}.\n * @returns The inferred timeline, carrying the key regions the analysis found\n * and how sure it is of each segment.\n */\n timeline(opts?: ChordTimelineOptions): Timeline {\n // The score's own reading when it is the score's own question, so the\n // documented order — timeline, phrases, keys, key — infers the harmony once\n // rather than once per member. Options name a different question, and one\n // asked with them neither reads the kept answer nor becomes it.\n const result =\n opts === undefined\n ? this.#chordAnalysis()\n : chordTimelineFromNotes(this.#data.notes, this.#analysisOptions(opts));\n return Timeline.fromData({\n segments: result.timeline.segments,\n totalBeats: opts?.totalBeats ?? this.totalBeats,\n keys: result.keys,\n segmentConfidence: result.segmentConfidence,\n });\n }\n\n /**\n * The key held longest across the score, when one can be read.\n *\n * A score carrying a key answers with it. Otherwise the key regions are\n * searched for and the one holding for the most beats wins, so a piece that\n * digresses is named by the key it keeps coming back to rather than by the\n * key it opens on. A score with nothing sounding has no key at all.\n *\n * @returns The prevailing key, or undefined when nothing sounds.\n */\n key(): Key | undefined {\n if (this.#key !== undefined) {\n return this.#key;\n }\n const prevailing = prevailingKeyOf(this.#keyRegions());\n return prevailing === null ? undefined : toKey(prevailing);\n }\n\n /**\n * Every key region the score passes through, in time order.\n *\n * A score that was told its key answers with that key across the whole of it,\n * as {@link Score.key} and {@link Score.timeline} do: the caller has already\n * answered the question, and searching for a modulation away from a stated\n * key would make the option read as a hint where it was given as an\n * instruction. Only `totalBeats` is read from the options there, since the\n * rest tune a search that is not run.\n *\n * @param opts Analysis options; see {@link KeyTimelineOptions}.\n * @returns The regions; empty when nothing sounds.\n */\n keys(opts?: KeyTimelineOptions): KeyRegion[] {\n if (opts !== undefined) {\n if (this.#key !== undefined) {\n return statedKeyRegions(this.#key, this.#data.notes, opts.totalBeats ?? this.totalBeats);\n }\n return keyTimelineFromNotes(this.#data.notes, { meters: this.#data.meters, ...opts });\n }\n // The reading the class keeps, copied on the way out: the key search is the\n // second most expensive thing here and every member that needs it reads the\n // one answer, so what a caller does with the regions it is handed must not\n // reach what the score reads next.\n return this.#keyRegions().map(copyKeyRegion);\n }\n\n /**\n * Every key the score could be in, ranked, read as one key across the whole\n * of it.\n *\n * {@link Score.keys} divides the score into the regions it passes through;\n * this ranks the readings of the score entire, so a caller can see what the\n * winner beat and by how much. Each note counts for its duration times its\n * velocity — the measure chord inference already weighs by — so the sustained\n * harmony that establishes a key outweighs a run of ornaments over it, which\n * is what makes a score the right thing to ask rather than a bare histogram\n * of its pitches.\n *\n * @param opts Which profile to rank with, whether the church modes take part,\n * whether each candidate explains itself, and the budget; the weights come\n * from the notes themselves, so they are not on offer.\n * @returns The candidates, best first; empty when nothing sounds.\n * @example\n * ```ts\n * import { Score } from '@libraz/libcantus';\n * const score = Score.of([{ pitch: 60, startBeat: 0, durationBeat: 4 }]);\n * score.detectKeys()[0]?.key.rootPc; // 0\n * ```\n */\n detectKeys(opts?: Omit<DetectKeyOptions, 'weights'>): DetectedKeyMatch[] {\n return detectKeyFromNotes(this.#data.notes, opts).map(detectedKeyMatch);\n }\n\n /**\n * The phrases the notes fall into.\n *\n * The cadences are read from the score's own harmony, so the chord timeline\n * does not have to be built and passed in by hand.\n *\n * @param opts Analysis options; see {@link PhraseOptions}.\n * @returns The phrases, in time order.\n */\n phrases(opts?: PhraseOptions): Phrase[] {\n return phrasesFromTimeline(this.#chordTimeline(), this.#data.notes, {\n meters: this.#data.meters,\n ...(this.#key === undefined ? {} : { key: keyIdentity(this.#key) }),\n ...opts,\n });\n }\n\n /**\n * The cadences that close the score's phrases, ranked by how much structure\n * each one closes.\n *\n * {@link Score.phrases} says where the phrases end; this says which of those\n * endings matter. Two chords alone cannot tell the close of a piece from a\n * passing confirmation halfway through a hyperbar, and a phrase reading can,\n * because it knows what the cadence closes and where that sits. Phrases no\n * cadence closes are left out.\n *\n * @param opts How the phrases are read; see {@link PhraseOptions}.\n * @returns The cadences, heaviest first; ties keep the earlier one.\n */\n structuralCadences(opts?: PhraseOptions): StructuralCadence[] {\n return structuralCadences(this.phrases(opts));\n }\n\n /**\n * The sections the score divides into.\n *\n * @param opts Analysis options; see {@link FormSectionOptions}.\n * @returns The sections, in time order.\n */\n sections(opts?: FormSectionOptions): FormSection[] {\n return sectionsFromNotes(this.#data.notes, { meters: this.#data.meters, ...opts });\n }\n\n /**\n * The bar-level pulse above the meter.\n *\n * The cadences come from the score's own harmony unless the caller passes\n * their own, so this reads the same grouping {@link Score.phrases} builds its\n * phrases on rather than a second one that ignores where the music closes.\n *\n * @param opts Analysis options; see {@link HypermeterOptions}.\n * @returns The grouping, its downbeats, a confidence, and a rationale.\n */\n hypermeter(opts?: HypermeterOptions): Hypermeter {\n return hypermeter(this.#data.notes, this.#data.meters, {\n cadenceBeats: this.#cadenceBeats(),\n ...opts,\n });\n }\n\n /**\n * The motifs the melody repeats.\n *\n * The plain analysis record comes back rather than a {@link Motif}, as it\n * does from every other reader here that is not {@link Score.timeline} or\n * {@link Score.key}: a `Motif` holds a bare cell of notes, so wrapping the\n * record would drop the intervals, the rhythmic profile, every later\n * occurrence and the rationale — the findings the extraction was asked for.\n * A record is a cell, so `Motif.fromData(found)` reaches the\n * transformations without anything being rebuilt by hand.\n *\n * A melody is one line, so a score holding several is read as its top voice:\n * notes struck together are one event and the highest of them stands for it.\n * A piano part read whole therefore answers for the voice a listener follows\n * rather than for a line assembled from the insides of its chords. Split the\n * score into lines first to have each of them answered for.\n *\n * @param opts Cell-length bounds and the recurrence threshold; see\n * {@link ExtractMotifsOptions}.\n * @returns The motifs found, longest first.\n * @example\n * ```ts\n * import { Motif, Score } from '@libraz/libcantus';\n * const score = Score.of([\n * { pitch: 60, startBeat: 0, durationBeat: 1 },\n * { pitch: 62, startBeat: 1, durationBeat: 1 },\n * { pitch: 64, startBeat: 2, durationBeat: 1 },\n * { pitch: 60, startBeat: 3, durationBeat: 1 },\n * { pitch: 62, startBeat: 4, durationBeat: 1 },\n * { pitch: 64, startBeat: 5, durationBeat: 1 },\n * ]);\n * const found = score.motifs()[0];\n * found?.occurrences.length; // 2\n * found === undefined ? undefined : Motif.fromData(found).notes.length; // 3\n * ```\n */\n motifs(opts?: ExtractMotifsOptions): MotifData[] {\n return extractMotifs(this.#data.notes, opts);\n }\n\n /**\n * The shape the melody traces.\n *\n * A contour is the shape of one line, so a score holding several is read as\n * its top voice: notes struck together are one event and the highest of them\n * stands for it, which keeps a chord from being measured as a climb through\n * its own notes. Split the score into lines first to have each of them\n * answered for; {@link Score.voices} is what reads the polyphony as polyphony.\n */\n contour(): MelodicContour {\n return melodicContour(this.#data.notes);\n }\n\n /**\n * Each note's role in the harmony sounding under it.\n *\n * The chord under each note and the key it is read in both come from the\n * score: the harmony from its own chord timeline, and the key from the\n * argument, then the carried key, then the regions the analysis found. A\n * score with no readable harmony — nothing sounding, or too little to name a\n * chord — reads every note against C major and no chord at all, which labels\n * the notes as the non-chord tones they are rather than failing.\n *\n * A score holds a whole piece rather than a single line, so the notes are read\n * as the polyphony they are: each note is classified in its own voice, against\n * everything else sounding under it. That is what a suspension needs — a\n * dissonance is dissonant against something — and it is what keeps a note of\n * one voice from being heard as the passing tone of another.\n *\n * @param key The key to read the notes in, as a key name, a plain key/scale,\n * or a {@link Key}; defaults to the score's own.\n * @returns One annotation per note, in the score's own time order.\n */\n voices(key?: KeyLike): AnalyzedNote[] {\n const timeline = this.#chordTimeline();\n return analyzePolyphony(this.#data.notes, timeline.at, this.#keyContext(key));\n }\n\n /**\n * The notes carrying the ids the voice analysis reports them back under.\n *\n * {@link Score.voices} answers about the notes; this hands back the notes\n * themselves with the handle each answer names, so a caller pairing an\n * annotation or a conflict with the note it describes has something to pair\n * it with. The id is the note's position in the score's own time order, which\n * is not necessarily the order the notes arrived in.\n *\n * @returns One voice note per note, in the score's own time order.\n */\n voiceNotes(): IdentifiedVoiceNote[] {\n return toVoiceNotes(this.#data.notes);\n }\n\n /**\n * Whether an instrument can play the score, and what makes it hard.\n *\n * The third layer asks how much time separates two notes, and the score\n * answers it from its whole tempo map: a passage under an accelerando is\n * judged at the tempo actually in force across it, the same integral\n * {@link Score.secondsAt} reports. The beats the issues name are the score's\n * own.\n *\n * @param instrument The instrument to play it on: a plain\n * {@link InstrumentProfile} or an {@link Instrument}.\n * @returns Difficulty, the issues found, and each note's placement.\n * @throws If the value names no instrument, or the instrument it names is\n * contradictory.\n * @example\n * ```ts\n * import { Instrument, Score } from '@libraz/libcantus';\n * const score = Score.of([{ pitch: 27, startBeat: 0, durationBeat: 1 }]);\n * score.playability(Instrument.bass4()).issues[0]?.type; // 'noteOutOfRange'\n * ```\n */\n playability(instrument: InstrumentProfileLike): PlayabilityReport {\n const profile = toInstrumentProfile(instrument);\n const tempo = this.#data.tempo;\n const openingBpm = tempoAt(0, tempo);\n if (tempo.length < 2) {\n // One marking governs the whole score, so it already is the tempo every\n // note is played at and there is nothing to integrate.\n return playability(this.#data.notes, profile, openingBpm);\n }\n // Otherwise each onset is restated as the beat it would fall on if the\n // score ran at its opening tempo throughout and took the same wall-clock\n // time to get there. That leaves the elapsed seconds between any two notes\n // exactly what the map says, which is what the scalar tempo the analysis\n // takes cannot express on its own.\n // The map is read once for the pass rather than once per note: an imported\n // accelerando marks a tempo every tick, and a conversion handed the map\n // afresh re-reads the whole of it to know it is still the map it validated.\n const played = tempoReader(tempo);\n const evenly = tempoReader([{ startBeat: 0, bpm: openingBpm }]);\n const restate = (beat: number): number => evenly.beatAt(played.secondsAt(beat));\n const scoreBeats = new Map<number, number>();\n const evenlyPaced = this.#data.notes.map((note) => {\n const startBeat = restate(note.startBeat);\n scoreBeats.set(startBeat, note.startBeat);\n return {\n ...note,\n startBeat,\n durationBeat: restate(note.startBeat + note.durationBeat) - startBeat,\n };\n });\n const report = playability(evenlyPaced, profile, openingBpm);\n return {\n ...report,\n issues: report.issues.map((issue) => ({\n ...issue,\n startBeat: scoreBeats.get(issue.startBeat) ?? issue.startBeat,\n })),\n };\n }\n\n /**\n * An index for repeated lookups over the notes.\n *\n * @param opts How the events are read; see {@link NoteEventIndexOptions}.\n * @returns The index.\n */\n index(opts?: NoteEventIndexOptions): NoteEventIndex {\n return createNoteEventIndex(this.#data.notes, {\n allowNonPositiveDuration: true,\n name: 'score notes',\n ...opts,\n });\n }\n\n /**\n * Where a beat falls in seconds, read through the tempo map.\n *\n * Every tempo segment the span crosses is integrated, so a beat after a\n * tempo change is not the change's tempo applied to the whole span. A beat\n * inside a pickup reports negative elapsed time, at the opening tempo.\n *\n * @param beat Position in quarter-note beats.\n * @returns Elapsed seconds from the tempo map's origin.\n */\n secondsAt(beat: number): number {\n return beatsToSeconds(beat, this.#data.tempo);\n }\n\n /**\n * Where a beat falls in bars, read through the meter map.\n *\n * @param beat Position in quarter-note beats.\n * @returns The 0-based bar and the quarter-note offset inside it; a pickup\n * reports bar -1.\n */\n barAt(beat: number): BarPosition {\n return beatToBarPosition(beat, this.#data.meters);\n }\n\n /**\n * The time signature sounding at a beat.\n *\n * @param beat Position in quarter-note beats.\n * @returns The signature in force there.\n */\n meterAt(beat: number): TimeSignature {\n return meterAt(beat, this.#data.meters);\n }\n\n /**\n * The score's beats as MIDI ticks, for a writer that counts in them.\n *\n * @param ppq Ticks per quarter note.\n * @returns The notes with tick-valued onsets and durations, in time order.\n */\n toTicks(ppq: number): NoteEvent[] {\n return this.#data.notes.map((note) => ({\n ...note,\n startBeat: beatsToTicks(note.startBeat, ppq),\n durationBeat: beatsToTicks(note.durationBeat, ppq),\n }));\n }\n\n /**\n * Whether another score holds the same notes in the same context.\n *\n * The comparison is made through the other score's public data, so two\n * scores built by different copies of the module still compare.\n *\n * @param other The score to compare.\n * @returns True when the notes, the meter, the tempo and the read key match.\n */\n equals(other: Score): boolean {\n const theirs = other.data;\n const mine = this.#data;\n return (\n mine.notes.length === theirs.notes.length &&\n mine.notes.every((note, index) => sameNote(note, theirs.notes[index])) &&\n mine.meters.length === theirs.meters.length &&\n mine.meters.every((change, index) => sameMeter(change, theirs.meters[index])) &&\n mine.tempo.length === theirs.tempo.length &&\n mine.tempo.every((event, index) => {\n const theirEvent = theirs.tempo[index];\n return (\n theirEvent !== undefined &&\n event.startBeat === theirEvent.startBeat &&\n event.bpm === theirEvent.bpm\n );\n }) &&\n sameKey(mine.key, theirs.key)\n );\n }\n\n /** A copy of the underlying plain data. */\n get data(): ScoreData {\n const copy: ScoreData = {\n notes: this.#data.notes.map(copyNoteEvent),\n meters: copyMeters(this.#data.meters),\n tempo: this.#data.tempo.map((event) => ({ startBeat: event.startBeat, bpm: event.bpm })),\n };\n if (this.#key !== undefined) {\n copy.key = this.#key.toJSON();\n }\n return copy;\n }\n\n /** The plain form of the score, for `JSON.stringify`. */\n toJSON(): ScoreData {\n return this.data;\n }\n\n /** The same context carrying another set of notes. */\n #withNotes(notes: readonly NoteEvent[]): Score {\n return new Score({ ...this.#data, notes: [...notes] });\n }\n\n /**\n * The same context carrying another set of notes, with a carried key moved\n * the same way the notes were.\n *\n * Every path that moves the pitches goes through here, so a score cannot come\n * back sounding in one key and analysed in another.\n */\n #moved(notes: readonly NoteEvent[], moveKey: (key: Key) => Key): Score {\n const data: ScoreData = { ...this.#data, notes: [...notes] };\n if (this.#key !== undefined) {\n data.key = moveKey(this.#key).toJSON();\n }\n return new Score(data);\n }\n\n /**\n * The chord timeline the score's own harmony describes, read once.\n *\n * Private, because the options belong to the members that expose them: the\n * analyses that read harmony read the score's, and a caller who wants\n * another builds it through {@link Score.timeline}. The reading is kept\n * because a score is immutable and this takes no options: chord inference is\n * the most expensive thing the class does, and the natural order — timeline,\n * phrases, cadences, voices — would otherwise ask for it once per member.\n */\n #chordTimeline(): ChordTimeline {\n return this.#chordAnalysis().timeline;\n }\n\n /**\n * The whole reading, not only the timeline it carries: the key regions and\n * the per-segment confidence come from the same pass, and {@link\n * Score.timeline} hands all three to the class it builds.\n */\n #chordAnalysis(): ChordTimelineResult {\n const analysis =\n this.#chords ?? chordTimelineFromNotes(this.#data.notes, this.#analysisOptions());\n this.#chords = analysis;\n return analysis;\n }\n\n /**\n * The key regions under the score: the key it was told it is in across the\n * whole of it, or the ones read from the notes against its own meter.\n *\n * Kept on first reading for the same reason the chord timeline is.\n */\n #keyRegions(): KeyRegion[] {\n const regions =\n this.#regions ??\n (this.#key === undefined\n ? keyTimelineFromNotes(this.#data.notes, { meters: this.#data.meters })\n : statedKeyRegions(this.#key, this.#data.notes, this.totalBeats));\n this.#regions = regions;\n return regions;\n }\n\n /** Where the score's own harmony closes, as beats. */\n #cadenceBeats(): number[] {\n return detectCadences(this.#chordTimeline(), this.#keyContext(undefined)).map(\n (hit) => hit.atBeat,\n );\n }\n\n /** The score's context as chord-timeline options, with the caller's on top. */\n #analysisOptions(opts?: ChordTimelineOptions): ChordTimelineOptions {\n return {\n meters: this.#data.meters,\n ...(this.#key === undefined ? {} : { key: keyIdentity(this.#key) }),\n ...opts,\n };\n }\n\n /**\n * The key each note is read against: the argument, then the carried key,\n * then the key in force at the beat, and C major where nothing sounds.\n */\n #keyContext(key: KeyLike | undefined): KeyContext {\n assertKeyArgument(key, 'score key');\n // One key travels whole; a key that changes over the piece is read per beat\n // and reduced to its pitch classes, since a lookup runs once per note and\n // no reading built on it asks how the key is written.\n if (key !== undefined) {\n return keyIdentity(toKey(key));\n }\n if (this.#key !== undefined) {\n return keyIdentity(this.#key);\n }\n const regions = this.#keyRegions();\n const prevailing = prevailingKeyOf(regions) ?? keyIdentity(Key.major('C'));\n const keyAt = keyLookup(regions, prevailing);\n return (beat) => scaleOf(keyAt(beat));\n }\n}\n\n/** Whether two plain note events hold the same note. */\nfunction sameNote(note: NoteEvent, other: NoteEvent | undefined): boolean {\n return (\n other !== undefined &&\n note.pitch === other.pitch &&\n note.startBeat === other.startBeat &&\n note.durationBeat === other.durationBeat &&\n note.velocity === other.velocity &&\n note.articulation === other.articulation\n );\n}\n\n/** Whether two meter changes name the same signature at the same beat. */\nfunction sameMeter(change: MeterMap[number], other: MeterMap[number] | undefined): boolean {\n if (other === undefined || change.startBeat !== other.startBeat) {\n return false;\n }\n const grouping = change.ts.grouping ?? [];\n const theirs = other.ts.grouping ?? [];\n return (\n change.ts.numerator === other.ts.numerator &&\n change.ts.denominator === other.ts.denominator &&\n grouping.length === theirs.length &&\n grouping.every((entry, index) => entry === theirs[index])\n );\n}\n\n/** Whether two scores were read in the same key, one having none included. */\nfunction sameKey(key: KeyData | undefined, other: KeyData | undefined): boolean {\n if (key === undefined || other === undefined) {\n return key === other;\n }\n return Key.fromJSON(key).equals(Key.fromJSON(other));\n}\n","import type {\n ArrangementAnalysis,\n ArrangementOptions,\n ArrangementSession,\n ArrangementTrack,\n Conflict,\n TensionPoint,\n TrackEdit,\n} from '../analyze/arrange/index.js';\nimport {\n analyzeArrangement,\n createArrangementSession,\n tensionCurveFrom,\n trackRoleOf,\n} from '../analyze/arrange/index.js';\nimport type { KeyRegion } from '../analyze/keys/index.js';\nimport type { ChordTimeline } from '../analyze/timeline/index.js';\nimport type { MeterLike } from '../core/meter/index.js';\nimport { resolveMeters, toMeterData } from '../core/meter/index.js';\nimport type { NoteEvent } from '../core/types.js';\nimport { assertInteger, assertPositiveInt, assertRange } from '../core/validation/index.js';\nimport type { ChordSegment } from '../theory/chord/index.js';\nimport { NoteSafety } from '../theory/safety/index.js';\nimport type { KeyLike } from '../theory/scale/index.js';\nimport { resolveKey } from '../theory/scale/index.js';\nimport type { ScoreOptions } from './score.js';\nimport { Score } from './score.js';\nimport {\n assertDataArray,\n assertDataObject,\n assertDataObjects,\n assertNoteEventArray,\n copyNoteEvent,\n copyPlain,\n samePlain,\n spanEnd,\n} from './shared.js';\nimport { Timeline } from './timeline.js';\n\n/**\n * The options an arrangement is read under, in the plain form\n * {@link Arrangement.data} carries them.\n *\n * Everything {@link analyzeArrangement} accepts, except that the harmony a\n * caller supplies is held as chord segments: a {@link ChordTimeline} carries a\n * lookup function, and no serialization can hold one.\n */\nexport type ArrangementSettings = Omit<ArrangementOptions, 'timeline'> & {\n /**\n * Chord segments to analyse against, instead of inferring the harmony from\n * the notes.\n */\n timeline?: ChordSegment[];\n};\n\n/**\n * How an arrangement is built: the settings it is read under, with the key\n * named any way the library names one and the harmony given as the timeline\n * the analysis functions take.\n */\nexport type ArrangementSetup = Omit<ArrangementSettings, 'key' | 'meters' | 'timeline'> & {\n /** The key the tracks are read in, when it is already known. */\n key?: KeyLike;\n /**\n * The meter the tracks are read against, as one time signature — `'6/8'` or\n * its data — or as the map of a piece that changes meter. Naming it here and\n * as `ts` too is an input error, since the two name the same thing.\n */\n meters?: MeterLike;\n /**\n * A chord timeline to analyse against, instead of inferring one from the\n * notes.\n */\n timeline?: ChordTimeline;\n};\n\n/** How an arrangement's tension is sampled: its settings, plus the step. */\nexport type ArrangementTensionOptions = ArrangementSetup & {\n /** Distance between samples in beats. */\n step?: number;\n};\n\n/** The plain form an {@link Arrangement} hands out and is rebuilt from. */\nexport type ArrangementData = {\n /**\n * The tracks, in the order they were given.\n *\n * The order is the caller's and is kept: an annotation and a conflict both\n * report the index a note had in the array it arrived in, so reordering the\n * notes here would make those indices point at other notes.\n */\n tracks: ArrangementTrack[];\n /** The options the tracks are read under; absent when they are all defaults. */\n settings?: ArrangementSettings;\n};\n\n/**\n * A track's notes checked and copied, in the order they were given.\n *\n * Zero-length notes are accepted, as they are everywhere on the analysis side:\n * a MIDI import carries them, and the analysis drops them itself.\n *\n * The array is checked as a whole before it is copied, under the budget the\n * settings name where they name one: a track the analysis would refuse for its\n * size is refused as it is taken on, rather than being stored and refused at\n * every reading afterwards.\n */\nfunction copyNotes(notes: readonly NoteEvent[], name: string, budget?: number): NoteEvent[] {\n return assertNoteEventArray(notes, name, { allowNonPositiveDuration: true, budget }).map(\n copyNoteEvent,\n );\n}\n\n/**\n * Defensive copy of one track, its notes and its role checked as they are\n * copied.\n *\n * The role is checked here as well as on the analysis side, since this is the\n * boundary a project file crosses: a role outside the table would be stored,\n * handed back by {@link Arrangement.tracks} as a {@link TrackRole}, and read as\n * pitched material by the harmony inference.\n */\nfunction copyTrack(track: ArrangementTrack, index: number, budget?: number): ArrangementTrack {\n assertDataObject(track, `tracks[${index}]`);\n const copy: ArrangementTrack = {\n notes: copyNotes(track.notes, `tracks[${index}].notes`, budget),\n };\n if (track.name !== undefined) {\n copy.name = track.name;\n }\n if (track.role !== undefined) {\n copy.role = trackRoleOf(track.role, `tracks[${index}].role`);\n }\n return copy;\n}\n\n/**\n * Key regions validated and copied by the class that owns the shape.\n *\n * A region carries a key, a confidence and a pivot chord, all of which\n * {@link Timeline} already refuses to hold a nonsensical value for; checking\n * them again here would be a second reading of the same rules.\n */\nfunction copyKeyRegions(keys: readonly KeyRegion[]): KeyRegion[] {\n const given = assertDataObjects<KeyRegion>(keys, 'arrangement keys');\n return [...new Timeline({ segments: [], totalBeats: 0, keys: [...given] }).keys];\n}\n\n/** Chord segments validated and copied by the class that owns the shape. */\nfunction copySegments(segments: readonly ChordSegment[]): ChordSegment[] {\n const given = assertDataObjects<ChordSegment>(segments, 'arrangement timeline');\n return [...new Timeline({ segments: [...given], totalBeats: spanEnd(given) }).segments];\n}\n\n/** The `{ at, segments }` shape the analysis functions take, over segments. */\nfunction chordTimelineOf(segments: readonly ChordSegment[]): ChordTimeline {\n return new Timeline({ segments: [...segments], totalBeats: spanEnd(segments) }).chordTimeline;\n}\n\n/**\n * Defensive copy of the settings, with every part validated.\n *\n * This is the boundary a project file or a hand-edited JSON crosses, so each\n * numeric option is checked here under the name it carries rather than\n * wherever the analysis first reads it — an option the analysis only consults\n * on one of its paths is checked on all of them.\n *\n * @param settings The settings as they arrived.\n * @param trackCount How many tracks they are read against.\n * @returns The copy, or undefined when nothing was set.\n * @throws If an option carries a value the analysis cannot hold.\n */\nfunction copySettings(\n settings: ArrangementSettings | undefined,\n trackCount: number,\n): ArrangementSettings | undefined {\n if (settings === undefined) {\n return undefined;\n }\n assertDataObject(settings, 'arrangement settings');\n const copy: ArrangementSettings = {};\n // The meter is read through the same resolver every meter-aware entry point\n // reads its options through, so an arrangement accepts exactly what they\n // accept and naming both `ts` and `meters` is the error it always was.\n const meters = resolveMeters({ ts: settings.ts, meters: settings.meters }, 'arrangement meters');\n if (settings.ts !== undefined) {\n // Resolved before it is copied, as `meters` is below: a value that stands\n // for a meter rather than being one — a `Meter` instance — carries the\n // signature behind a method, so copying it as it arrived stores `{}` and\n // the stored arrangement can no longer be read back.\n copy.ts = copyPlain(toMeterData(settings.ts, 'arrangement ts'), 'arrangement ts');\n }\n if (settings.meters !== undefined) {\n copy.meters = copyPlain(meters, 'arrangement meters');\n }\n if (settings.key !== undefined) {\n copy.key = resolveKey(settings.key);\n }\n if (settings.keys !== undefined) {\n copy.keys = copyKeyRegions(settings.keys);\n }\n if (settings.timeline !== undefined) {\n copy.timeline = copySegments(settings.timeline);\n }\n if (settings.harmonyTracks !== undefined) {\n copy.harmonyTracks = assertDataArray<number>(\n settings.harmonyTracks,\n 'arrangement harmonyTracks',\n ).map((track, index) =>\n assertInteger(track, `arrangement harmonyTracks[${index}]`, 0, trackCount - 1),\n );\n }\n if (settings.minSeverity !== undefined) {\n copy.minSeverity = assertInteger(\n settings.minSeverity,\n 'arrangement minSeverity',\n NoteSafety.Safe,\n NoteSafety.Dissonant,\n );\n }\n if (settings.pickupBeats !== undefined) {\n copy.pickupBeats = assertRange(\n settings.pickupBeats,\n 0,\n Number.MAX_SAFE_INTEGER,\n 'arrangement pickupBeats',\n );\n }\n if (settings.harmonicRhythm !== undefined) {\n copy.harmonicRhythm = assertRange(\n settings.harmonicRhythm,\n Number.MIN_VALUE,\n Number.MAX_SAFE_INTEGER,\n 'arrangement harmonicRhythm',\n );\n }\n if (settings.profile !== undefined) {\n copy.profile = settings.profile;\n }\n if (settings.budget !== undefined) {\n copy.budget = assertPositiveInt(settings.budget, 'arrangement budget', Number.MAX_SAFE_INTEGER);\n }\n return Object.keys(copy).length === 0 ? undefined : copy;\n}\n\n/** Defensive copy of plain arrangement data, with every part validated. */\nfunction copyArrangement(data: ArrangementData): ArrangementData {\n assertDataObject(data, 'arrangement data');\n // The budget is read before the tracks are copied so that the notes are held\n // to the bound the settings name; a value that names no budget is refused by\n // the same check, and again by `copySettings` under its own name.\n const budget = data.settings?.budget;\n const tracks = assertDataArray<ArrangementTrack>(data.tracks, 'arrangement tracks').map(\n (track, index) => copyTrack(track, index, budget),\n );\n const settings = copySettings(data.settings, tracks.length);\n return settings === undefined ? { tracks } : { tracks, settings };\n}\n\n/** The plain data a set of tracks and settings describe. */\nfunction arrangementData(\n tracks: readonly ArrangementTrack[],\n settings: ArrangementSettings | undefined,\n): ArrangementData {\n const data: ArrangementData = {\n tracks: [...assertDataArray<ArrangementTrack>(tracks, 'tracks')],\n };\n if (settings !== undefined) {\n data.settings = settings;\n }\n return data;\n}\n\n/** The settings a caller's setup describes, in the plain form data carries. */\nfunction settingsFrom(setup: ArrangementSetup | undefined): ArrangementSettings | undefined {\n if (setup === undefined) {\n return undefined;\n }\n assertDataObject(setup, 'arrangement options');\n const { key, meters, timeline, ...rest } = setup;\n const settings: ArrangementSettings = { ...rest };\n if (key !== undefined) {\n settings.key = resolveKey(key);\n }\n if (meters !== undefined) {\n settings.meters = resolveMeters({ meters }, 'arrangement meters');\n }\n if (timeline !== undefined) {\n assertDataObject(timeline, 'arrangement timeline');\n settings.timeline = [\n ...assertDataArray<ChordSegment>(timeline.segments, 'arrangement timeline segments'),\n ];\n }\n return settings;\n}\n\n/** A caller's setup as the analysis functions take it: the key and the meter differ. */\nfunction analysisOptionsOf(\n setup: ArrangementTensionOptions | undefined,\n): ArrangementOptions & { step?: number } {\n if (setup === undefined) {\n return {};\n }\n assertDataObject(setup, 'arrangement options');\n const { key, meters, ...rest } = setup;\n const opts: ArrangementOptions & { step?: number } = { ...rest };\n if (key !== undefined) {\n opts.key = resolveKey(key);\n }\n if (meters !== undefined) {\n opts.meters = resolveMeters({ meters }, 'arrangement meters');\n }\n return opts;\n}\n\n/**\n * Several named tracks read together, with the analysis of how they fit.\n *\n * One harmony is inferred from every pitched track pooled together, each track\n * is annotated against it, and the notes that clash with the chord sounding\n * beneath them are collected as conflicts — the whole of\n * {@link analyzeArrangement}, held as a value instead of as a call whose\n * result a caller has to carry alongside the notes it was made from.\n *\n * The analysis is held open across edits: {@link Arrangement.update} works out\n * which beats an edit could have reached and recomputes those, so a host that\n * re-analyses on every keystroke pays for the beats that changed. The\n * arrangement it returns is a new one — an arrangement never changes, so the\n * reading taken before an edit stays valid and a host can keep it for undo.\n *\n * A member that has another class to answer with answers with it:\n * {@link Arrangement.track} hands back a {@link Score} and\n * {@link Arrangement.timeline} a {@link Timeline}, so a caller stays in the\n * class API rather than being handed the arrays behind it.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Arrangement } from '@libraz/libcantus';\n * const arrangement = Arrangement.of([\n * { name: 'melody', role: 'melody', notes: [{ pitch: 72, startBeat: 0, durationBeat: 4 }] },\n * { name: 'bass', role: 'bass', notes: [{ pitch: 48, startBeat: 0, durationBeat: 4 }] },\n * ]);\n * arrangement.track('melody')?.totalBeats; // 4\n * ```\n */\nexport class Arrangement {\n readonly #data: ArrangementData;\n /**\n * The open analysis, made on first read and then kept.\n *\n * Deferred rather than made in the constructor: rebuilding an arrangement\n * from stored data, or reading the tracks back out of one, asks nothing of\n * the analysis, and an update hands its own analysis to the arrangement it\n * returns rather than having it made twice.\n */\n #open: ArrangementSession | undefined;\n\n /**\n * Wrap plain arrangement data.\n *\n * @param data The tracks and the settings they are read under; copied, never\n * retained.\n * @throws If a note, the meter, or one of the settings carries a value the\n * analysis cannot hold.\n */\n constructor(data: ArrangementData) {\n this.#data = copyArrangement(data);\n }\n\n /**\n * Build an arrangement from tracks.\n *\n * A track carrying no name is named for its position — `'track 1'`,\n * `'track 2'` — which is the name the analysis reports for it, and the name\n * {@link Arrangement.track} finds it under. A track carrying no role plays\n * `'other'`; only `'drums'` changes the analysis, whose pitches name\n * instruments rather than harmony and are kept out of the inferred key and\n * chords.\n *\n * @param tracks The tracks, in the order the caller holds them.\n * @param opts The key, meter, harmony and budget to read them under; see\n * {@link ArrangementSetup}.\n * @returns The arrangement.\n * @example\n * ```ts\n * import { Arrangement } from '@libraz/libcantus';\n * const arrangement = Arrangement.of(\n * [{ name: 'lead', notes: [{ pitch: 60, startBeat: 0, durationBeat: 4 }] }],\n * { key: 'C major' },\n * );\n * arrangement.tracks.length; // 1\n * ```\n */\n static of(tracks: readonly ArrangementTrack[], opts?: ArrangementSetup): Arrangement {\n return new Arrangement(arrangementData(tracks, settingsFrom(opts)));\n }\n\n /** Rebuild an arrangement from the plain data {@link Arrangement.data} hands out. */\n static fromData(data: ArrangementData): Arrangement {\n return new Arrangement(data);\n }\n\n /** Rebuild an arrangement from its {@link Arrangement.toJSON} output. */\n static fromJSON(data: ArrangementData): Arrangement {\n return new Arrangement(data);\n }\n\n /** The tracks as they were given, in that order. */\n get tracks(): readonly ArrangementTrack[] {\n return copyPlain(this.#data.tracks, 'arrangement tracks');\n }\n\n /**\n * The reading of the whole arrangement: the key regions, the harmony, the\n * cadences, each track's annotated notes, and the conflicts.\n *\n * @returns The analysis {@link analyzeArrangement} makes of these tracks.\n */\n get analysis(): ArrangementAnalysis {\n const { timeline, ...rest } = this.#session().analysis;\n return { ...copyPlain(rest, 'arrangement analysis'), timeline: this.timeline().chordTimeline };\n }\n\n /**\n * The notes clashing with the harmony sounding beneath them, worst severity\n * first.\n *\n * Every ordinary non-chord tone — a passing note, a neighbour, a prepared\n * suspension — is unsafe against the chord under it by definition, so this\n * is a report rather than a fault list; each conflict carries the note's\n * labels to tell those apart.\n */\n get conflicts(): Conflict[] {\n return copyPlain(this.#session().analysis.conflicts, 'arrangement conflicts');\n }\n\n /**\n * One track's notes as a score, or undefined when no track carries the name.\n *\n * The score is read against the arrangement's meter, and against its key\n * when the arrangement was given one; the harmony the tracks spell out\n * together is what {@link Arrangement.analysis} and\n * {@link Arrangement.timeline} report, since a track read on its own is not\n * read against what sounds beneath it. A score holds its notes in time\n * order, which is not necessarily the order this track's notes arrived in.\n *\n * @param name The track's name, as the analysis reports it.\n * @returns The score, or undefined.\n */\n track(name: string): Score | undefined {\n const index = this.#session().analysis.tracks.findIndex((track) => track.name === name);\n const track = index < 0 ? undefined : this.#data.tracks[index];\n return track === undefined ? undefined : Score.of(track.notes, this.#scoreOptions());\n }\n\n /**\n * Re-analyse after replacing the notes of one or more tracks.\n *\n * The analysis is not made again from nothing: the open reading works out\n * which beats the edit could have reached, recomputes those, and carries the\n * rest over, and the arrangement returned takes that analysis on. What it\n * reports is what a fresh {@link Arrangement.of} over the edited tracks\n * reports — the same segments, keys, cadences, annotations and conflicts;\n * only the work differs.\n *\n * @param edits The tracks whose notes changed, each with the notes it holds\n * after the edit.\n * @returns A new arrangement over the edited tracks; this one is unchanged.\n * @throws If an edit names no track of this arrangement, or carries a note\n * the analysis cannot read.\n * @example\n * ```ts\n * import { Arrangement } from '@libraz/libcantus';\n * const arrangement = Arrangement.of([\n * { name: 'lead', notes: [{ pitch: 60, startBeat: 0, durationBeat: 4 }] },\n * ]);\n * const moved = arrangement.update([\n * { trackIndex: 0, notes: [{ pitch: 62, startBeat: 0, durationBeat: 4 }] },\n * ]);\n * moved.tracks[0]?.notes[0]?.pitch; // 62\n * arrangement.tracks[0]?.notes[0]?.pitch; // 60\n * ```\n */\n update(edits: readonly TrackEdit[]): Arrangement {\n // The reading keeps the arrays it is handed, so it is handed copies: an\n // arrangement must not be reachable through an array a caller still holds.\n const copied: TrackEdit[] = [];\n for (let index = 0; index < edits.length; index += 1) {\n const edit = edits[index];\n if (edit === undefined) {\n continue;\n }\n copied.push({\n trackIndex: edit.trackIndex,\n notes: copyNotes(edit.notes, `edits[${index}].notes`, this.#data.settings?.budget),\n });\n }\n const session = this.#session().update(copied);\n const next = new Arrangement(arrangementData(session.tracks, this.#data.settings));\n next.#adopt(session);\n return next;\n }\n\n /**\n * The harmonic tension across the arrangement, sampled at regular beats.\n *\n * The harmony is the one the arrangement already found, so the curve and the\n * annotations describe the same chords rather than two readings of the same\n * notes.\n *\n * Naming a key, its regions, or the tracks the harmony is read from asks for\n * a harmony this arrangement did not find, so the curve is read under the one\n * named rather than over the one it holds.\n *\n * @param opts The sampling step, and any setting to lay over the\n * arrangement's own; a meter named here replaces the arrangement's, since\n * `ts` and `meters` name the same thing.\n * @returns One tension reading per sampled beat, in beat order.\n */\n tension(opts?: ArrangementTensionOptions): TensionPoint[] {\n return tensionCurveFrom(\n [...this.#data.tracks],\n this.#session().analysis,\n this.#layered(analysisOptionsOf(opts)),\n );\n }\n\n /**\n * The whole reading of the arrangement in one call, made afresh.\n *\n * {@link Arrangement.analysis} answers the same question about the\n * arrangement as it stands, and is the member to reach for: it is made once\n * and kept across edits. This one runs {@link analyzeArrangement} again over\n * the same tracks under settings laid on top of the arrangement's own, which\n * is what a caller narrowing the conflict list, restricting the harmony to a\n * few tracks, or reading the piece against a key it does not carry wants —\n * without building a second arrangement to hold that reading.\n *\n * @param opts Any setting to lay over the arrangement's own; a meter named\n * here replaces the arrangement's, since `ts` and `meters` name the same\n * thing.\n * @returns The inferred harmony, per-track annotations, cadences, and\n * conflicts.\n * @throws If a setting carries a value the analysis cannot hold, or the\n * tracks exceed the budget.\n */\n analyze(opts?: ArrangementSetup): ArrangementAnalysis {\n return analyzeArrangement([...this.#data.tracks], this.#layered(analysisOptionsOf(opts)));\n }\n\n /**\n * The harmony the tracks spell out together, in time.\n *\n * @returns The inferred timeline, carrying the key regions the analysis\n * found under it.\n */\n timeline(): Timeline {\n const { timeline, keys } = this.#session().analysis;\n return Timeline.fromData({\n segments: [...timeline.segments],\n // The analysis reports where the chords and the keys end rather than the\n // span it ran over, so the span is read back off them.\n totalBeats: spanEnd(timeline.segments, keys),\n keys: [...keys],\n });\n }\n\n /**\n * Whether another arrangement holds the same tracks under the same settings.\n *\n * The comparison is made through the other arrangement's public data, so two\n * arrangements built by different copies of the module still compare. The\n * analysis is not compared: it is what these tracks and these settings\n * produce, so two arrangements agreeing on both agree on it.\n *\n * @param other The arrangement to compare.\n * @returns True when the tracks and the settings match.\n */\n equals(other: Arrangement): boolean {\n return samePlain(this.#data, other.data);\n }\n\n /** A copy of the underlying plain data. */\n get data(): ArrangementData {\n return copyPlain(this.#data, 'arrangement data');\n }\n\n /** The plain form of the arrangement, for `JSON.stringify`. */\n toJSON(): ArrangementData {\n return this.data;\n }\n\n /** The open reading, analysing the tracks on the first call. */\n #session(): ArrangementSession {\n const open =\n this.#open ?? createArrangementSession([...this.#data.tracks], this.#analysisOptions());\n this.#open = open;\n return open;\n }\n\n /**\n * Take on an analysis an update has already made.\n *\n * Private to the class rather than to the instance, which is what lets an\n * update hand its incremental reading to the arrangement it returns instead\n * of that arrangement making the same reading again.\n */\n #adopt(session: ArrangementSession): void {\n this.#open = session;\n }\n\n /** The stored settings as the options the analysis functions take. */\n #analysisOptions(): ArrangementOptions {\n const settings = this.#data.settings;\n if (settings === undefined) {\n return {};\n }\n const { timeline, ...rest } = settings;\n return timeline === undefined ? { ...rest } : { ...rest, timeline: chordTimelineOf(timeline) };\n }\n\n /**\n * The arrangement's own options with a caller's laid over them.\n *\n * A meter named by the caller replaces the arrangement's rather than joining\n * it: `ts` and `meters` name the same thing, and carrying one of each is the\n * input error the resolver refuses.\n */\n #layered<T extends ArrangementOptions>(theirs: T): T & ArrangementOptions {\n const mine = this.#analysisOptions();\n const { ts, meters, ...withoutMeter } = mine;\n const inherited = theirs.ts === undefined && theirs.meters === undefined ? mine : withoutMeter;\n return { ...inherited, ...theirs };\n }\n\n /** The context one track's notes are read as a score against. */\n #scoreOptions(): ScoreOptions {\n const settings = this.#data.settings;\n const opts: ScoreOptions = {};\n if (settings?.meters !== undefined) {\n opts.meters = settings.meters;\n } else if (settings?.ts !== undefined) {\n opts.meters = settings.ts;\n }\n if (settings?.key !== undefined) {\n opts.key = settings.key;\n }\n return opts;\n }\n}\n","import { InvalidInputError } from '../core/errors/index.js';\nimport type {\n Articulation,\n InstrumentProfile,\n InstrumentProfileLike,\n Limb,\n PercussionProfile,\n PlayabilityReport,\n StringedProfile,\n StringFingering,\n} from '../core/instrument/index.js';\nimport {\n BASS_4_STRING,\n BASS_5_STRING,\n GUITAR_DROP_D,\n GUITAR_STANDARD,\n playability,\n toInstrumentProfile,\n type ValidatedProfile,\n} from '../core/instrument/index.js';\nimport { fingeringsIn, foldIn, rangeIn, soundsIn } from '../core/instrument/profile.js';\nimport type { NoteLike } from '../core/pitch/index.js';\nimport { toNoteData } from '../core/pitch/index.js';\nimport type { NoteEvent } from '../core/types.js';\nimport { assertMidiPitch } from '../core/validation/index.js';\nimport type { TransposingInstrument } from '../theory/transposition/index.js';\nimport { toSoundingPitch } from '../theory/transposition/index.js';\nimport { Note } from './note.js';\n\n/** Whether two lists hold the same values in the same order. */\nfunction sameList<T>(a: readonly T[], b: readonly T[]): boolean {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n}\n\n/** Whether two kits place the same limbs on the same voices. */\nfunction sameReach(a: PercussionProfile['reach'], b: PercussionProfile['reach']): boolean {\n const keys = Object.keys(a);\n return (\n keys.length === Object.keys(b).length &&\n keys.every((key) => sameList(a[Number(key)] ?? [], b[Number(key)] ?? []))\n );\n}\n\n/**\n * A copy of a profile, lists and all, so a caller's object cannot become\n * library state and a profile handed out cannot be edited from underneath the\n * instrument that holds it.\n */\nfunction copyProfile(profile: InstrumentProfile): InstrumentProfile {\n const common = {\n name: profile.name,\n articulations: [...profile.articulations],\n polyphony: profile.polyphony,\n };\n if (profile.kind === 'stringed') {\n const stringed: StringedProfile = {\n kind: 'stringed',\n ...common,\n tuning: [...profile.tuning],\n frets: profile.frets,\n maxStretch: profile.maxStretch,\n };\n // Carried only when the neck has none, so a profile that was copied and one\n // that was written by hand serialize to the same object.\n if (profile.fretless === true) {\n stringed.fretless = true;\n }\n return stringed;\n }\n const reach: Record<number, readonly Limb[]> = {};\n for (const [pitch, limbs] of Object.entries(profile.reach)) {\n reach[Number(pitch)] = [...limbs];\n }\n const percussion: PercussionProfile = {\n kind: 'percussion',\n ...common,\n limbs: [...profile.limbs],\n reach,\n };\n // Carried only when the kit names one, so a profile that was copied and one\n // that was written by hand serialize to the same object.\n if (profile.overdub !== undefined) {\n percussion.overdub = [...profile.overdub];\n }\n return percussion;\n}\n\n/**\n * A copy of a profile whose numbers the instrument can hold.\n *\n * A fret count that is not a whole number, or a string tuned to no pitch,\n * describes an instrument that answers every question and means none of them:\n * the range it reports, the positions it offers and the passages it accepts are\n * all read off these numbers. What counts as holdable is the instrument\n * module's own reading — the class states no second one, so an instrument and\n * the function it delegates to cannot come to differ over the same profile.\n */\nfunction checkedProfile(profile: InstrumentProfileLike): ValidatedProfile {\n // Copied field by field out of a profile that has just been checked, so the\n // copy holds the same values under the same names and is checked by the same\n // reading; copying first would mean spreading lists that are not yet known to\n // be lists.\n return copyProfile(toInstrumentProfile(profile)) as ValidatedProfile;\n}\n\n/**\n * An immutable instrument: what it physically is — an open-string tuning and a\n * fret count, or the voices each limb reaches — with the range, the positions\n * and the playability checks of the instrument module bound to it. A thin\n * convenience wrapper over a plain {@link InstrumentProfile}.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Instrument } from '@libraz/libcantus';\n * Instrument.guitar().fingerings(64).length; // 6\n * Instrument.bass4().canSound(27); // false\n * ```\n */\nexport class Instrument {\n readonly #profile: ValidatedProfile;\n\n private constructor(profile: ValidatedProfile) {\n this.#profile = profile;\n }\n\n /**\n * Wrap a plain instrument profile, whether a built-in one or a caller's own.\n *\n * An `Instrument` is accepted too, and comes back as an equal one: the\n * factory is the boundary a profile crosses everywhere in the library, so it\n * takes the same {@link InstrumentProfileLike} every other entry point does\n * rather than making a caller unwrap what it already holds.\n *\n * @param profile The plain profile, or an instrument standing for one.\n * @returns The wrapped instrument.\n * @throws If the profile describes no instrument: a neck with no strings, a\n * fret count that is not a whole number, a kit no limb reaches, or a\n * tuning, stretch or voice count that is not finite.\n * @example\n * ```ts\n * import { GUITAR_DROP_D } from '@libraz/libcantus/core';\n * import { Instrument } from '@libraz/libcantus';\n * Instrument.of(GUITAR_DROP_D).range().low; // 38\n * ```\n */\n static of(profile: InstrumentProfileLike): Instrument {\n return new Instrument(checkedProfile(profile));\n }\n\n /**\n * Six-string guitar in standard tuning: E2 A2 D3 G3 B3 E4.\n *\n * @returns The instrument.\n */\n static guitar(): Instrument {\n return Instrument.of(GUITAR_STANDARD);\n }\n\n /**\n * Six-string guitar in drop D: the lowest string down a tone to D2, the rest\n * standard.\n *\n * @returns The instrument.\n */\n static guitarDropD(): Instrument {\n return Instrument.of(GUITAR_DROP_D);\n }\n\n /**\n * Electric bass in standard tuning: E1 A1 D2 G2.\n *\n * @returns The instrument.\n */\n static bass4(): Instrument {\n return Instrument.of(BASS_4_STRING);\n }\n\n /**\n * Five-string bass with the low B: B0 E1 A1 D2 G2.\n *\n * @returns The instrument.\n * @example\n * ```ts\n * import { Instrument } from '@libraz/libcantus';\n * Instrument.bass5().range().low; // 23\n * ```\n */\n static bass5(): Instrument {\n return Instrument.of(BASS_5_STRING);\n }\n\n /**\n * Rebuild an instrument from the plain profile {@link Instrument.data} hands\n * out.\n *\n * @param data The plain profile.\n * @returns The wrapped instrument.\n * @throws If the profile describes no instrument; see {@link Instrument.of}.\n */\n static fromData(data: InstrumentProfile): Instrument {\n return Instrument.of(data);\n }\n\n /**\n * Rebuild an instrument from its {@link Instrument.toJSON} output.\n *\n * @param data The serialized profile.\n * @returns The wrapped instrument.\n * @throws If the profile describes no instrument; see {@link Instrument.of}.\n */\n static fromJSON(data: InstrumentProfile): Instrument {\n return Instrument.of(data);\n }\n\n /** The instrument's name, as its profile carries it. */\n get name(): string {\n return this.#profile.name;\n }\n\n /** Which family the instrument belongs to. */\n get kind(): InstrumentProfile['kind'] {\n return this.#profile.kind;\n }\n\n /** Greatest number of notes that can sound at once. */\n get polyphony(): number {\n return this.#profile.polyphony;\n }\n\n /** A copy of the techniques the instrument can produce. */\n get articulations(): Articulation[] {\n return [...this.#profile.articulations];\n }\n\n /** A copy of the underlying plain profile. */\n get data(): InstrumentProfile {\n return this.toJSON();\n }\n\n /**\n * The lowest and highest pitch the instrument sounds.\n *\n * Derived from the tuning and the fret count, or from the voices the\n * player's limbs reach, rather than stored — and not necessarily gapless, so\n * {@link Instrument.canSound} answers for one pitch.\n *\n * @returns The extreme sounding pitches as MIDI numbers, inclusive.\n * @example\n * ```ts\n * import { Instrument } from '@libraz/libcantus';\n * Instrument.guitar().range(); // { low: 40, high: 88 }\n * ```\n */\n range(): { low: number; high: number } {\n return rangeIn(this.#profile);\n }\n\n /**\n * Whether the instrument has this pitch at all.\n *\n * @param pitch MIDI pitch.\n * @returns True when some string and fret, or some limb the player has,\n * produces it.\n */\n canSound(pitch: number): boolean {\n assertMidiPitch(pitch, 'pitch');\n return soundsIn(this.#profile, pitch);\n }\n\n /**\n * Every position on the neck that sounds a pitch, lowest string first.\n *\n * @param pitch MIDI pitch.\n * @returns One entry per string that reaches the pitch; empty when none does.\n * @throws If the instrument is a kit, which has no neck to place a pitch on.\n */\n fingerings(pitch: number): StringFingering[] {\n const profile = this.#profile;\n if (profile.kind !== 'stringed') {\n throw new InvalidInputError(`${profile.name} has no strings to finger`);\n }\n assertMidiPitch(pitch, 'pitch');\n return fingeringsIn(profile, pitch);\n }\n\n /**\n * Move a pitch by whole octaves until the instrument can sound it, which is\n * what a player does with a line written below the instrument.\n *\n * @param pitch MIDI pitch to place.\n * @returns The nearest octave transposition the instrument sounds, taking the\n * upper one when two are equally near; the pitch unchanged when no\n * transposition is available.\n * @example\n * ```ts\n * import { Instrument } from '@libraz/libcantus';\n * Instrument.bass4().foldIntoRange(27); // 39\n * ```\n */\n foldIntoRange(pitch: number): number {\n assertMidiPitch(pitch, 'pitch');\n return foldIn(pitch, this.#profile);\n }\n\n /**\n * The pitch this instrument sounds for a note written in its part.\n *\n * Most parts are written at the pitch they sound, but some are not: a guitar\n * part is printed an octave above concert pitch, and a part for an instrument\n * in B flat or in A is printed in a different key altogether. The instrument\n * is looked up by its own name, so an instrument the transposition table\n * carries needs nothing said; name a transposition to read a part for one it\n * does not, which is every instrument whose profile is the caller's own.\n *\n * The interval decides the letter, so the spelling of the part survives: on a\n * clarinet in A a written D sharp sounds B sharp, where a semitone count\n * alone would answer C natural and lose the letter the part is written on.\n *\n * @param note A note name, a MIDI number, plain note data, or a `Note`, as\n * the player reads it.\n * @param transposition The written-to-sounding transposition to read the part\n * under; the instrument's own name by default.\n * @returns The sounding note, at concert pitch.\n * @throws If the note is malformed, or the transposition is neither a known\n * instrument name nor a spelled interval — which is what an instrument the\n * table does not carry reports when none is named.\n * @example\n * ```ts\n * import { Instrument } from '@libraz/libcantus';\n * Instrument.guitar().soundingPitch('C4').name; // 'C3'\n * Instrument.bass4().soundingPitch('C4', '-P8').name; // 'C3'\n * ```\n */\n soundingPitch(note: NoteLike, transposition: TransposingInstrument = this.#profile.name): Note {\n return new Note(toSoundingPitch(toNoteData(note), transposition));\n }\n\n /**\n * Judge whether a passage can be played on this instrument, and how hard it\n * is.\n *\n * Nothing is rewritten or rejected: the report names what stands in the way,\n * and only the tempo-dependent layer consults `bpm`, so omitting the tempo\n * reports what the instrument alone decides.\n *\n * @param notes The passage, in any order. Drum hits qualify as note events.\n * @param bpm Tempo in quarter-note beats per minute; enables the layer that\n * asks whether there is time for the movement.\n * @returns Difficulty, the issues found, and each note's string/fret or limb.\n * @throws If the notes are not note events, or the tempo is not a finite\n * positive number of beats per minute.\n * @example\n * ```ts\n * import { Instrument } from '@libraz/libcantus';\n * const report = Instrument.bass4().playability([\n * { pitch: 27, startBeat: 0, durationBeat: 1 },\n * ]);\n * report.issues[0]?.type; // 'noteOutOfRange'\n * ```\n */\n playability(notes: readonly NoteEvent[], bpm?: number): PlayabilityReport {\n return playability(notes, this.#profile, bpm);\n }\n\n /**\n * Whether another instrument is described identically.\n *\n * @param other The instrument to compare with.\n * @returns True when both profiles name the same instrument, string for\n * string or voice for voice.\n */\n equals(other: Instrument): boolean {\n // The other instrument is read through its public surface rather than its\n // private field: a bundler that emits two copies of this class — as a\n // CommonJS build without shared chunks does for the root and /model\n // entries — would otherwise throw on the brand check.\n const a = this.#profile;\n const b = other.data;\n if (a.name !== b.name || a.kind !== b.kind || a.polyphony !== b.polyphony) {\n return false;\n }\n if (!sameList(a.articulations, b.articulations)) {\n return false;\n }\n if (a.kind === 'stringed') {\n return (\n b.kind === 'stringed' &&\n a.frets === b.frets &&\n a.maxStretch === b.maxStretch &&\n (a.fretless ?? false) === (b.fretless ?? false) &&\n sameList(a.tuning, b.tuning)\n );\n }\n return (\n b.kind === 'percussion' &&\n sameList(a.limbs, b.limbs) &&\n sameReach(a.reach, b.reach) &&\n sameList(a.overdub ?? [], b.overdub ?? [])\n );\n }\n\n /**\n * The plain profile, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(instrument)` from collapsing to `{}`.\n *\n * @returns A copy of the underlying profile, its lists included.\n */\n toJSON(): InstrumentProfile {\n return copyProfile(this.#profile);\n }\n\n /**\n * The instrument's name, so a template literal or a log line reads as the\n * instrument.\n *\n * @returns The name, e.g. `'guitar'`.\n * @example\n * ```ts\n * import { Instrument } from '@libraz/libcantus';\n * Instrument.guitar().toString(); // 'guitar'\n * ```\n */\n toString(): string {\n return this.#profile.name;\n }\n}\n","import type { ChordTimeline } from '../analyze/timeline/index.js';\nimport { InvalidInputError } from '../core/errors/index.js';\nimport type { InstrumentProfile, InstrumentProfileLike } from '../core/instrument/profile.js';\nimport { toStringedProfile } from '../core/instrument/profile.js';\nimport type { MeterLike, MeterMap, TimeSignature } from '../core/meter/index.js';\nimport { beatsPerBar, meterAt, resolveMeters } from '../core/meter/index.js';\nimport type { PositionalRng } from '../core/random/index.js';\nimport { assertFiniteNumber } from '../core/validation/index.js';\nimport type { BassLineOptions, BassSegment } from '../generate/bass/index.js';\nimport { generateBassLine } from '../generate/bass/index.js';\nimport type { Complexity, GenerationContext } from '../generate/context/index.js';\nimport { resolveContext } from '../generate/context/index.js';\nimport type { CounterMelodyOptions } from '../generate/countermelody/index.js';\nimport { generateCounterMelody } from '../generate/countermelody/index.js';\nimport type { DrumsOptions } from '../generate/drums/index.js';\nimport { generateDrums } from '../generate/drums/index.js';\nimport type { HarmonizeOptions } from '../generate/harmonize/index.js';\nimport { harmonizeMelody } from '../generate/harmonize/index.js';\nimport type { ProgressionOptions } from '../generate/progression/index.js';\nimport { generateProgression } from '../generate/progression/index.js';\nimport type { Vocabulary } from '../generate/vocabulary/types.js';\nimport type { ChordSpan } from '../theory/chord/index.js';\nimport type { KeyLike, ResolvedKey } from '../theory/scale/index.js';\nimport { resolveKey } from '../theory/scale/index.js';\nimport { Instrument } from './instrument.js';\nimport type { ScoreOptions } from './score.js';\nimport { Score } from './score.js';\nimport { assertDataObject, assertDataObjects, copyPlain, samePlain } from './shared.js';\nimport { Timeline } from './timeline.js';\n\n/** The settings a composer holds and hands to every generator it drives. */\nexport type ComposerOptions = {\n /** The key the parts are written in. */\n key?: KeyLike;\n /** The meter, as one time signature — `'6/8'` or its data — or a map of changes. */\n meters?: MeterLike;\n /** Tempo in quarter-note beats per minute. */\n bpm?: number;\n /** The seed every part's own stream is derived from. */\n seed?: number;\n /** The complexity dials. */\n complexity?: Complexity;\n /**\n * The instrument each named part is written for, as a plain\n * {@link InstrumentProfile} or an {@link Instrument}. The settings a composer\n * hands back carry the plain form, the way a key handed in as a name comes\n * back as key/scale data.\n */\n instruments?: Record<string, InstrumentProfileLike>;\n /** Extra material the generators may draw from. */\n vocabulary?: readonly Vocabulary<unknown>[];\n /**\n * The algorithm version the parts are generated under; defaults to the\n * version this build produces. Naming it is what closes a reproduction\n * recipe: a seed alone reproduces a piece only for as long as the algorithms\n * behind it stay where they were, and a project that recorded the version it\n * was written under can ask for that version back.\n */\n algorithmVersion?: number;\n /**\n * Draw from this source instead of one derived from `seed`. Each part still\n * addresses its own namespace, so parts do not collide.\n *\n * A live handle rather than settings, so it is held by reference and left out\n * of the plain data {@link Composer.data} hands back: a source cannot be\n * written to a project file, and copying one would hand back a second stream\n * rather than the same one.\n */\n rng?: PositionalRng;\n};\n\n/**\n * How a bass line is written: what {@link BassLineOptions} asks for minus the\n * settings the composer already holds, with the instrument taken the way the\n * rest of the class API takes one.\n */\nexport type BassLineSettings = Omit<\n BassLineOptions,\n 'segments' | 'key' | 'ts' | 'ctx' | 'instrument'\n> & {\n /**\n * The instrument the line is written for, as a plain {@link StringedProfile}\n * or an {@link Instrument}. Giving one is itself the request that the line be\n * playable on it: `octave` then says where in that instrument to aim rather\n * than which absolute band to use, and where the two disagree the instrument\n * wins — a note below the lowest string comes back an octave up, the way a\n * player would take it. Leave it out for a programmed part.\n */\n instrument?: InstrumentProfileLike;\n};\n\n/**\n * How a counter line is written: what {@link CounterMelodyOptions} asks for\n * minus the settings the composer already holds, with the harmony taken the way\n * {@link Composer.bass} takes it.\n */\nexport type CounterMelodySettings = Omit<\n CounterMelodyOptions,\n 'melody' | 'key' | 'ts' | 'ctx' | 'timeline'\n> & {\n /**\n * The harmony to write against, as a {@link Timeline} or the plain chord\n * timeline the analysis layer hands out. A timeline carries its own segment\n * boundaries, so a chord change anywhere — including off the generator's\n * half-beat probe grid — is seen; prefer it over `chordAt`.\n */\n timeline?: Timeline | ChordTimeline;\n};\n\n/** What a harmonization gives back: the chords, and the melody they fit. */\nexport type HarmonizedMelody = {\n /** The chords, in time. */\n chords: Timeline;\n /**\n * The melody as the chords read it. Harmonizing may move the melody into the\n * key the chords are in, so this is the line that actually sounds against\n * them; the untransposed input would not.\n */\n melody: Score;\n /** How far the melody was moved, in semitones. */\n transposeSemitones: number;\n};\n\n/**\n * The plain chord timeline a harmony value stands for.\n *\n * Read through the public surface rather than by `instanceof`, so a timeline\n * built by a second copy of the module is followed like any other — the same\n * reading {@link Composer.bass} and {@link Motif.develop} take.\n */\nfunction toChordTimeline(harmony: Timeline | ChordTimeline): ChordTimeline {\n return 'chordTimeline' in harmony ? harmony.chordTimeline : harmony;\n}\n\n/** A copy of the dials, carrying only the ones the caller named. */\nfunction copyComplexity(complexity: Complexity): Complexity {\n assertDataObject(complexity, 'composer complexity');\n const copy: Complexity = {};\n for (const dial of ['rhythmic', 'harmonic', 'ornament', 'difficulty'] as const) {\n const value = complexity[dial];\n if (value !== undefined) {\n copy[dial] = assertFiniteNumber(value, `composer complexity ${dial}`);\n }\n }\n return copy;\n}\n\n/** A copy of the instrument each part is written for, each one validated. */\nfunction copyInstruments(\n instruments: Record<string, InstrumentProfileLike>,\n): Record<string, InstrumentProfile> {\n assertDataObject(instruments, 'composer instruments');\n const copy: Record<string, InstrumentProfile> = {};\n for (const [part, profile] of Object.entries(instruments)) {\n // Checked and copied by the class that speaks for a profile everywhere\n // else, so a composer accepts exactly the instruments an instrument does.\n copy[part] = Instrument.of(profile).data;\n }\n return copy;\n}\n\n/**\n * A deep copy of the settings in the canonical plain form.\n *\n * A key becomes the plain key every generator takes — whole, carrying the\n * tonic it was named with, so a piece written in Ab minor is not handed on as\n * one in G# minor — and a bare time signature becomes the meter map the whole\n * model layer reads, so the settings a composer hands out are the settings it\n * hands on. The meter is materialized\n * because a composer that names none is read in 4/4 exactly as one that names\n * it is; the key is not, because a composer with no key harmonizes by inferring\n * one, which is a different request from harmonizing in C major.\n *\n * The seed and the algorithm version are materialized for the same reason the\n * meter is, and it is what makes these settings a reproduction recipe: a\n * project file that recorded neither reopens under whatever the build it is\n * opened on happens to default to, which is a different piece under the same\n * name and nothing in the saved file to say so.\n */\nfunction copyOptions(options: ComposerOptions): ComposerOptions {\n assertDataObject(options, 'composer options');\n const copy: ComposerOptions = {\n meters: resolveMeters({ meters: options.meters }, 'composer meters'),\n };\n if (options.key !== undefined) {\n copy.key = resolveKey(options.key);\n }\n if (options.bpm !== undefined) {\n copy.bpm = options.bpm;\n }\n if (options.seed !== undefined) {\n copy.seed = options.seed;\n }\n if (options.algorithmVersion !== undefined) {\n copy.algorithmVersion = options.algorithmVersion;\n }\n if (options.complexity !== undefined) {\n copy.complexity = copyComplexity(options.complexity);\n }\n if (options.instruments !== undefined) {\n copy.instruments = copyInstruments(options.instruments);\n }\n if (options.vocabulary !== undefined) {\n copy.vocabulary = assertDataObjects<Vocabulary<unknown>>(\n options.vocabulary,\n 'composer vocabulary',\n ).map((entry, index) => copyPlain(entry, `composer vocabulary[${index}]`));\n }\n if (options.rng !== undefined) {\n // Carried by reference: the source is a handle on a stream, and a copy of\n // it would be a second stream drawing the same numbers twice.\n copy.rng = options.rng;\n }\n // Resolved through the same resolver every generator reads the settings\n // through, so the concrete seed and version written here are the ones the\n // parts were actually drawn under rather than a second reading of the\n // defaults.\n const resolved = resolveContext(contextOf(copy));\n copy.seed = resolved.seed;\n copy.algorithmVersion = resolved.algorithmVersion;\n return copy;\n}\n\n/** The context half of a set of settings, as the generators read it. */\nfunction contextOf(options: ComposerOptions): GenerationContext {\n const ctx: GenerationContext = {};\n if (options.seed !== undefined) {\n ctx.seed = options.seed;\n }\n if (options.algorithmVersion !== undefined) {\n ctx.algorithmVersion = options.algorithmVersion;\n }\n if (options.rng !== undefined) {\n ctx.rng = options.rng;\n }\n if (options.bpm !== undefined) {\n ctx.bpm = options.bpm;\n }\n if (options.complexity !== undefined) {\n ctx.complexity = copyComplexity(options.complexity);\n }\n if (options.instruments !== undefined) {\n ctx.instruments = copyInstruments(options.instruments);\n }\n if (options.vocabulary !== undefined) {\n ctx.vocabulary = assertDataObjects<Vocabulary<unknown>>(\n options.vocabulary,\n 'composer vocabulary',\n ).map((entry, index) => copyPlain(entry, `composer vocabulary[${index}]`));\n }\n return ctx;\n}\n\n/**\n * Where a harmonized span ends.\n *\n * The melody's own end, and never before the last chord: the chords are placed\n * on a grid laid over the melody, and a timeline built to a span the last chord\n * starts on would drop that chord instead of sounding it. The last slot is as\n * long as the one before it, and a bar where there is only one.\n */\nfunction harmonizedSpan(melodyEnd: number, chords: readonly ChordSpan[], barBeats: number): number {\n const last = chords[chords.length - 1];\n if (last === undefined) {\n return melodyEnd;\n }\n const previous = chords[chords.length - 2];\n const slot = previous === undefined ? barBeats : last.startBeat - previous.startBeat;\n return Math.max(melodyEnd, last.startBeat + slot);\n}\n\n/**\n * The settings a piece is generated under, held in one place and handed to\n * every part.\n *\n * The generation context — seed, tempo, complexity dials, instruments,\n * vocabulary — was already designed to be shared across the parts of one\n * piece, and `resolveContext(...).part(name)` already gives each part its own\n * stream from a single seed. What was missing was something to hold the shared\n * half, so callers wrote `key`, `ts`, and `ctx: { seed }` again at every call.\n * A `Composer` is that holder: set it once, and each generator inherits it.\n *\n * Every part a composer writes is scored against the composer's own meter and\n * tempo, and the pitched ones in its key, so the scores it hands back line up\n * with each other without being re-contextualized one at a time.\n *\n * A composer that names no key writes no pitched part: {@link Composer.bass},\n * {@link Composer.progression} and {@link Composer.counterMelody} refuse rather\n * than fall back on a key of the library's choosing, which would be a piece in\n * a key nobody asked for with nothing to say so. {@link Composer.drums} carries\n * no key and is written either way, and {@link Composer.harmonize} reads a key\n * off the melody it is given; `with({ key })` carries that key over to the\n * parts written after it.\n *\n * Immutable like every other class here: `withSeed` and friends return a new\n * composer rather than reconfiguring this one, so a variation can be written\n * beside the original instead of replacing it.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Composer } from '@libraz/libcantus';\n * const composer = Composer.of({ key: 'C major', bpm: 96, seed: 7 });\n * composer.progression({ style: 'dance', bars: 4 }).totalBeats; // 16\n * composer.withSeed(8).data.seed; // 8\n * ```\n */\nexport class Composer {\n readonly #options: ComposerOptions;\n readonly #meters: MeterMap;\n readonly #key: ResolvedKey | undefined;\n\n /**\n * Wrap the settings a piece is generated under.\n *\n * @param options The shared key, meter, tempo, and context; copied, never\n * retained.\n * @throws If the key names no key, the meter map is malformed, or the seed,\n * tempo, dials, instruments or vocabulary carry a value the generators\n * cannot hold.\n */\n constructor(options: ComposerOptions) {\n // The context half is checked by the resolver every generator reads it\n // through — inside `copyOptions`, which resolves the seed and the version\n // it stores — so a composer accepts exactly the seeds, tempos, dials and\n // dictionaries they accept, at the point the settings are named rather than\n // at the first part written under them.\n this.#options = copyOptions(options);\n this.#meters = resolveMeters({ meters: this.#options.meters }, 'composer meters');\n this.#key = this.#options.key === undefined ? undefined : resolveKey(this.#options.key);\n }\n\n /**\n * Start from a set of settings.\n *\n * @param options The shared key, meter, tempo, and context.\n * @returns The composer.\n */\n static of(options: ComposerOptions): Composer {\n return new Composer(options);\n }\n\n /** Rebuild a composer from the plain data {@link Composer.data} hands out. */\n static fromData(data: ComposerOptions): Composer {\n return new Composer(data);\n }\n\n /** Rebuild a composer from its {@link Composer.toJSON} output. */\n static fromJSON(data: ComposerOptions): Composer {\n return new Composer(data);\n }\n\n /** The same settings with some of them replaced. */\n with(patch: Partial<ComposerOptions>): Composer {\n return new Composer({ ...this.#options, ...patch });\n }\n\n /** The same settings in a different key. */\n withKey(key: KeyLike): Composer {\n return this.with({ key });\n }\n\n /** The same settings from a different seed. */\n withSeed(seed: number): Composer {\n return this.with({ seed });\n }\n\n /** The same settings at different complexity. */\n withComplexity(complexity: Complexity): Composer {\n return this.with({ complexity });\n }\n\n /**\n * A chord progression, in time.\n *\n * The chords are laid out one per bar of the composer's own meter, so a chord\n * change falls on a bar line of the piece and the timeline spans `bars` of it:\n * four beats each in 4/4, three in 3/4, and three in 6/8. Every other part is\n * written against that grid, and harmony that is not on it drifts further from\n * the bar line with every repeat.\n *\n * @param opts Everything the progression generator takes but the key, the\n * meter and the context, which are the composer's.\n * @returns The chords over the beats they sound for.\n * @throws If the composer names no key: the chords are degrees of one, and\n * there is no melody here to read a key from the way\n * {@link Composer.harmonize} does.\n * @throws If the composer's meter changes: one chord per bar has no single bar\n * length to be laid out on, and the chords would leave the bar lines at the\n * first change rather than follow them.\n */\n progression(opts: Omit<ProgressionOptions, 'key' | 'ctx' | 'ts'>): Timeline {\n const key = this.#requireKey('progression');\n const ts = this.#unchangingMeter('progression');\n const chords = generateProgression({ ...opts, key, ts, ctx: this.context });\n return Timeline.fromChords(chords, opts.bars * beatsPerBar(ts), key);\n }\n\n /**\n * A drum part.\n *\n * A drum onset is a note event carrying a General MIDI pitch, so the hits are\n * a score like any other and read against the composer's meter and tempo. It\n * carries no key: a kit is not in one, and naming a key here would invite the\n * pitched analyses to read the kit map as melody.\n *\n * @param opts Everything the drum generator takes but the meter and the\n * context, which are the composer's.\n * @returns The hits, as a score.\n * @throws If the composer's meter is not 4/4 throughout, which is the only\n * meter the drum patterns are written against: a piece that opens in 4/4\n * and changes later has bars the patterns cannot be laid out on, so the\n * request is refused rather than answered with 4/4 bars over the change.\n */\n drums(opts: Omit<DrumsOptions, 'ts' | 'ctx'>): Score {\n const hits = generateDrums({ ...opts, ts: this.#unchangingMeter('drums'), ctx: this.context });\n return Score.of(hits, this.#scoreOptions());\n }\n\n /**\n * A bass line under a harmony.\n *\n * @param source The harmony to follow: a timeline, or the chord segments one\n * is made of.\n * @param opts Everything the bass generator takes but the segments, the key,\n * the meter and the context; see {@link BassLineSettings}.\n * @returns The line, as a score in the composer's key.\n * @throws If the composer names no key: the line is written in one, and a\n * default key would put the part in a key the caller never asked for.\n * @throws If the instrument names a kit, which has no strings for a bass line\n * to be placed on.\n * @example\n * ```ts\n * import { Composer, Instrument } from '@libraz/libcantus';\n * const composer = Composer.of({ key: 'C major', seed: 3 });\n * const plan = composer.progression({ style: 'dance', bars: 2 });\n * composer.bass(plan, { style: 'pop', instrument: Instrument.bass4() }).notes.length > 0; // true\n * ```\n */\n bass(source: Timeline | readonly BassSegment[], opts?: BassLineSettings): Score {\n // Read through the public surface rather than by `instanceof`, so a\n // timeline built by a second copy of the module is followed like any other.\n const segments: readonly BassSegment[] = Array.isArray(source)\n ? (source as readonly BassSegment[])\n : (source as Timeline).segments;\n const key = this.#requireKey('bass');\n const { instrument, ...rest } = opts ?? {};\n const notes = generateBassLine({\n ...rest,\n ...(instrument === undefined\n ? {}\n : { instrument: toStringedProfile(instrument, 'bass instrument') }),\n segments,\n key,\n ts: this.#openingMeter(),\n ctx: this.context,\n });\n return Score.of(notes, this.#scoreOptions(key));\n }\n\n /**\n * A second line against a melody.\n *\n * Only the melody's notes cross over; the meter, the tempo and the key the\n * line is written against are the composer's, so a counter line and the part\n * it answers are read in one context.\n *\n * The harmony crosses over the way {@link Composer.bass} takes it: a\n * {@link Timeline} or the plain chord timeline, so a caller holding the\n * class does not have to unwrap it for one of the two methods.\n *\n * @param melody The lead line to write against.\n * @param opts Everything the counter-melody generator takes but the melody,\n * the key, the meter and the context; see {@link CounterMelodySettings}.\n * @returns The counter line, as a score in the composer's key.\n * @throws If the composer names no key: the line is written in one, and the\n * melody it answers is not read for a key here — {@link Composer.harmonize}\n * is the member that does that.\n */\n counterMelody(melody: Score, opts?: CounterMelodySettings): Score {\n const key = this.#requireKey('counterMelody');\n const { timeline, ...rest } = opts ?? {};\n const notes = generateCounterMelody({\n ...rest,\n ...(timeline === undefined ? {} : { timeline: toChordTimeline(timeline) }),\n melody: melody.notes,\n key,\n ts: this.#openingMeter(),\n ctx: this.context,\n });\n return Score.of(notes, this.#scoreOptions(key));\n }\n\n /**\n * Chords under a melody, with the melody the chords read.\n *\n * A composer that names a key harmonizes in it; one that names none has the\n * key estimated from the melody, which is what the harmonizer does when it is\n * asked for chords and given nothing else.\n *\n * @param melody The melody to harmonize.\n * @param opts Everything the harmonizer takes but the melody, the key, the\n * meter and the context.\n * @returns The chords, the melody as they read it, and the distance between\n * that melody and the one handed in.\n * @example\n * ```ts\n * import { Composer, Score } from '@libraz/libcantus';\n * const composer = Composer.of({ key: 'C major' });\n * const melody = Score.of([{ pitch: 60, startBeat: 0, durationBeat: 4 }]);\n * composer.harmonize(melody).transposeSemitones; // 0\n * ```\n */\n harmonize(\n melody: Score,\n opts?: Omit<HarmonizeOptions, 'melody' | 'key' | 'ts' | 'ctx'>,\n ): HarmonizedMelody {\n const result = harmonizeMelody({\n ...opts,\n melody: melody.notes,\n ...(this.#key === undefined ? {} : { key: this.#key }),\n ts: this.#openingMeter(),\n ctx: this.context,\n });\n const moved = melody.transpose(result.transposeSemitones);\n const totalBeats = harmonizedSpan(\n moved.totalBeats,\n result.chords,\n beatsPerBar(this.#openingMeter()),\n );\n return {\n chords: Timeline.fromChords(result.chords, totalBeats, result.key),\n // Scored in the key the chords are in rather than the composer's: where\n // the harmonizer moved the line, that is the key it now sounds in.\n melody: Score.of(moved.notes, this.#scoreOptions(result.key)),\n transposeSemitones: result.transposeSemitones,\n };\n }\n\n /**\n * Whether another composer holds the same settings.\n *\n * The comparison is made through the other composer's public data, so two\n * composers built by different copies of the module still compare. Both sides\n * are projected the same way: comparing the settings held here against the\n * data the other hands out answered \"different\" for a composer holding a\n * source and \"same\" for two that draw from different ones.\n *\n * A source is compared by identity, being a handle on a stream rather than a\n * setting: two composers drawing from different sources write different\n * parts, and the numbers a source will hand out cannot be read from it.\n *\n * @param other The composer to compare.\n * @returns True when both would generate the same parts.\n */\n equals(other: Composer): boolean {\n return samePlain(this.data, other.data) && this.context.rng === other.context.rng;\n }\n\n /** The resolved context, for handing back to the function API. */\n get context(): GenerationContext {\n return contextOf(this.#options);\n }\n\n /**\n * A copy of the settings this composer holds: the seed, the resolved\n * algorithm version and the rest of the recipe, so a piece can be written\n * again from what a project file stored.\n *\n * The source a composer was handed is left out, being a live handle rather\n * than plain data; a composer built with one keeps it across\n * {@link Composer.with} and its siblings.\n */\n get data(): ComposerOptions {\n return copyOptions({ ...this.#options, rng: undefined });\n }\n\n /** The plain form of the settings, for `JSON.stringify`. */\n toJSON(): ComposerOptions {\n return this.data;\n }\n\n /**\n * The key a pitched part is written in.\n *\n * A composer that names none is refused rather than written in C major: a\n * default key is an answer the caller never gave, and the part would come\n * back sounding like a piece nobody asked for with nothing to say it had\n * been substituted. {@link Composer.harmonize} is the one member that can\n * answer without a key, because it has a melody to read one from; the key it\n * found comes back with the harmonization, and `with({ key })` is how it is\n * handed to the parts written next.\n */\n #requireKey(part: string): ResolvedKey {\n if (this.#key === undefined) {\n throw new InvalidInputError(\n `composer ${part} needs a key for the part it writes; the composer names none — ` +\n 'give it one, or take the key harmonize reads off a melody and pass it on with with({ key })',\n );\n }\n return this.#key;\n }\n\n /**\n * The signature the parts are written against.\n *\n * Each generator names one time signature rather than a map, so a composer\n * whose meter changes hands over the signature its music opens on — the same\n * reading {@link Score.humanize} and its siblings take.\n */\n #openingMeter(): TimeSignature {\n return meterAt(0, this.#meters);\n }\n\n /**\n * The one signature a part laid out in bars is written against.\n *\n * A part that places material bar by bar has to know how long a bar is, and a\n * piece that changes meter has no one answer: the request is refused rather\n * than answered on the bar the piece opens in, which would put every bar after\n * the change somewhere the piece has no bar line.\n */\n #unchangingMeter(part: string): TimeSignature {\n if (this.#meters.length > 1) {\n throw new InvalidInputError(\n `composer ${part} needs one meter for the whole part; the composer changes meter`,\n );\n }\n return this.#openingMeter();\n }\n\n /** The context every score a composer hands back is read against. */\n #scoreOptions(key?: KeyLike): ScoreOptions {\n const opts: ScoreOptions = { meters: this.#meters };\n if (this.#options.bpm !== undefined) {\n opts.tempo = this.#options.bpm;\n }\n if (key !== undefined) {\n opts.key = key;\n }\n return opts;\n }\n}\n","import type { DurationData, NoteValue, SpelledDuration, Tuplet } from '../core/duration/index.js';\nimport { beatsToDuration, beatsToTiedDurations, durationToBeats } from '../core/duration/index.js';\n\n/**\n * A defensive copy of a written duration, with its dot count stated.\n *\n * The reading is the check: `durationToBeats` runs the duration module's own\n * validation — the base values it knows, the dot ceiling, the tuplet bounds —\n * so a duration arriving from a project file is held to exactly the rules a\n * duration built here is, without this layer restating any of them.\n */\nfunction copyDuration(value: NoteValue | DurationData): SpelledDuration {\n durationToBeats(value);\n if (typeof value === 'string') {\n return { base: value, dots: 0 };\n }\n const spelled: SpelledDuration = { base: value.base, dots: value.dots ?? 0 };\n if (value.tuplet !== undefined) {\n spelled.tuplet = { actual: value.tuplet.actual, normal: value.tuplet.normal };\n }\n return spelled;\n}\n\n/**\n * An immutable written duration: the note value a score shows — a base value,\n * its augmentation dots, and an optional tuplet ratio — and the beats it\n * lasts. A thin convenience wrapper over the duration module's plain value.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Duration } from '@libraz/libcantus';\n * Duration.ofBeats(1.5).spelled; // { base: 'quarter', dots: 1 }\n * ```\n */\nexport class Duration {\n readonly #base: NoteValue;\n readonly #dots: number;\n readonly #tuplet: Tuplet | undefined;\n\n private constructor(value: NoteValue | DurationData) {\n const spelled = copyDuration(value);\n this.#base = spelled.base;\n this.#dots = spelled.dots;\n this.#tuplet = spelled.tuplet;\n }\n\n /**\n * Build a duration from its parts.\n *\n * @param base The base note value, from the whole note down to the\n * sixty-fourth.\n * @param dots Augmentation dots; up to four are accepted.\n * @param tuplet Optional tuplet ratio: `{ actual: 3, normal: 2 }` writes\n * three notes in the time of two.\n * @returns The duration.\n * @throws If the base value is unknown, the dot count is not an integer in\n * 0..4, or a tuplet side is not a positive integer.\n */\n static of(base: NoteValue, dots = 0, tuplet?: Tuplet): Duration {\n return new Duration(tuplet === undefined ? { base, dots } : { base, dots, tuplet });\n }\n\n /**\n * Spell a length in beats as the note value a score would show.\n *\n * The spelling is the conventional one: 1.5 beats is a dotted quarter rather\n * than a quarter tied to an eighth, and a third of a beat is an eighth\n * triplet rather than a twenty-fourth note.\n *\n * @param beats The length in beats.\n * @param options `beatUnit` sets what one beat is; a quarter note by\n * default.\n * @returns The duration that spells the length.\n * @throws If the length is not positive, or — as a `NoSolutionError` — if no\n * single note value spells it, as for 5 beats. Use\n * {@link Duration.tieChain} for those.\n */\n static ofBeats(beats: number, options: { beatUnit?: NoteValue | DurationData } = {}): Duration {\n return new Duration(beatsToDuration(beats, options));\n }\n\n /**\n * Spell a length in beats as a chain of tied durations.\n *\n * A length with a single spelling comes back as a one-element chain.\n * Anything else is broken into plain and dotted values, longest first. The\n * chain knows nothing of barlines or beat grouping — an engraver splits\n * further at those — and it uses no tuplets.\n *\n * @param beats The length in beats.\n * @param options `beatUnit` sets what one beat is; a quarter note by\n * default.\n * @returns The tied durations, longest first, summing to the length.\n * @throws If the length is not positive, if the chain would exceed the\n * generation budget, or — as a `NoSolutionError` — if no chain of plain and\n * dotted values sums to it.\n * @example\n * ```ts\n * import { Duration } from '@libraz/libcantus';\n * Duration.tieChain(5).map((value) => value.toString()); // ['whole', 'quarter']\n * ```\n */\n static tieChain(\n beats: number,\n options: { beatUnit?: NoteValue | DurationData } = {},\n ): Duration[] {\n return beatsToTiedDurations(beats, options).map((spelled) => new Duration(spelled));\n }\n\n /**\n * Wrap a plain duration, or a bare base value as shorthand for an undotted\n * one.\n *\n * @param data The plain duration.\n * @returns The wrapped duration.\n * @throws If the base value is unknown, the dot count is not an integer in\n * 0..4, or a tuplet side is not a positive integer.\n */\n static fromData(data: NoteValue | DurationData): Duration {\n return new Duration(data);\n }\n\n /**\n * Rebuild a duration from its {@link Duration.toJSON} output.\n *\n * @param data The serialized duration.\n * @returns The wrapped duration.\n * @throws If the base value is unknown, the dot count is not an integer in\n * 0..4, or a tuplet side is not a positive integer.\n */\n static fromJSON(data: NoteValue | DurationData): Duration {\n return new Duration(data);\n }\n\n /** The base note value, from the whole note down to the sixty-fourth. */\n get base(): NoteValue {\n return this.#base;\n }\n\n /** Augmentation dots, 0 when the value carries none. */\n get dots(): number {\n return this.#dots;\n }\n\n /** A copy of the tuplet ratio, or undefined outside a tuplet. */\n get tuplet(): Tuplet | undefined {\n return this.#tuplet === undefined\n ? undefined\n : { actual: this.#tuplet.actual, normal: this.#tuplet.normal };\n }\n\n /**\n * A copy of the written value, with the dot count always stated: the shape\n * the duration module spells a length as.\n */\n get spelled(): SpelledDuration {\n return this.toJSON();\n }\n\n /** A copy of the underlying plain duration, the same value as {@link Duration.spelled}. */\n get data(): SpelledDuration {\n return this.toJSON();\n }\n\n /**\n * The length of the written value in beats.\n *\n * @param options `beatUnit` sets what one beat is; a quarter note by\n * default, so a dotted quarter reads as 1.5. Pass\n * `{ base: 'quarter', dots: 1 }` to count in the felt beats of a compound\n * meter.\n * @returns The length in beats.\n * @throws If the beat unit is not a duration the library reads.\n * @example\n * ```ts\n * import { Duration } from '@libraz/libcantus';\n * Duration.of('quarter', 1).beats(); // 1.5\n * ```\n */\n beats(options: { beatUnit?: NoteValue | DurationData } = {}): number {\n return durationToBeats(this.toJSON(), options);\n }\n\n /**\n * Whether another duration is written identically.\n *\n * Two values of the same length are not equal unless they are written the\n * same way: a dotted quarter and a quarter in the time of a triplet half\n * both last 1.5 beats and are different notations.\n *\n * @param other The duration to compare with.\n * @returns True when base, dots, and tuplet all match.\n */\n equals(other: Duration): boolean {\n // The other duration is read through its public surface rather than its\n // private fields: a bundler that emits two copies of this class — as a\n // CommonJS build without shared chunks does for the root and /model\n // entries — would otherwise throw on the brand check.\n const b = other.data;\n return (\n this.#base === b.base &&\n this.#dots === b.dots &&\n this.#tuplet?.actual === b.tuplet?.actual &&\n this.#tuplet?.normal === b.tuplet?.normal\n );\n }\n\n /**\n * The plain duration, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(duration)` from collapsing to `{}`. The tuplet appears\n * only on a value that carries one, which is the shape the duration module\n * produces.\n *\n * @returns A copy of the base value, dot count, and tuplet.\n */\n toJSON(): SpelledDuration {\n return this.#tuplet === undefined\n ? { base: this.#base, dots: this.#dots }\n : {\n base: this.#base,\n dots: this.#dots,\n tuplet: { actual: this.#tuplet.actual, normal: this.#tuplet.normal },\n };\n }\n\n /**\n * The written value, so a template literal or a log line reads as the\n * duration.\n *\n * @returns The base value, a dot per augmentation dot, and the tuplet ratio\n * when it has one, e.g. `'quarter.'` or `'eighth 3:2'`.\n */\n toString(): string {\n const dots = '.'.repeat(this.#dots);\n const ratio =\n this.#tuplet === undefined ? '' : ` ${this.#tuplet.actual}:${this.#tuplet.normal}`;\n return `${this.#base}${dots}${ratio}`;\n }\n}\n","import type { ParseResult } from '../core/errors/index.js';\nimport type { BarPosition, TimeSignature } from '../core/meter/index.js';\nimport {\n beatsPerBar,\n beatToBarPosition,\n formatBarPosition,\n formatTimeSignature,\n isCompound,\n isStrongBeat,\n metricWeight,\n parseTimeSignature,\n pulseBeats,\n pulsesPerBar,\n tryParseTimeSignature,\n tuplet,\n} from '../core/meter/index.js';\nimport { copyTimeSignature } from './shared.js';\n\n/**\n * An immutable time signature: a numerator over a note-value denominator, with\n * the optional grouping that gives an additive metre its felt beats. A thin\n * convenience wrapper over the meter module's plain time signature.\n *\n * One signature, not a piece's meter over time: a piece that changes meter is\n * described by a meter map, which the meter module's own functions read.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Meter } from '@libraz/libcantus';\n * Meter.parse('6/8').isCompound; // true\n * ```\n */\nexport class Meter {\n readonly #ts: TimeSignature;\n\n private constructor(ts: TimeSignature) {\n this.#ts = copyTimeSignature(ts);\n }\n\n /**\n * Build a meter from its parts.\n *\n * @param numerator Beats in a bar, counted in denominator units.\n * @param denominator The note value one unit is written as, e.g. 8 for an\n * eighth note.\n * @param grouping Optional grouping of the bar into felt beats, as positive\n * integers summing to the pulse count or to the numerator — `[2, 2, 3]`\n * for a 2+2+3 reading of 7/8.\n * @returns The meter.\n * @throws If the numerator or denominator is not a positive integer, or the\n * grouping sums to neither the pulse count nor the numerator.\n */\n static of(numerator: number, denominator: number, grouping?: number[]): Meter {\n return new Meter(\n grouping === undefined ? { numerator, denominator } : { numerator, denominator, grouping },\n );\n }\n\n /**\n * Parse a time signature such as `'4/4'`, `'6/8'`, or the additive `'2+2+3/8'`.\n *\n * @param text The signature text.\n * @returns The meter that text names.\n * @throws If the text is not `n/d` with positive integers, or names a\n * signature the library rejects. Use {@link Meter.tryParse} where failure\n * is ordinary, such as a meter field read on every keystroke.\n */\n static parse(text: string): Meter {\n return new Meter(parseTimeSignature(text));\n }\n\n /**\n * Parse a time signature, reporting failure instead of throwing it.\n *\n * The same reading as {@link Meter.parse} — that method is this one with its\n * error thrown — for the callers where text that does not parse yet is the\n * normal state of the input rather than a fault.\n *\n * @param text The signature text.\n * @returns The meter, or the error explaining why the text is not one.\n * @example\n * ```ts\n * import { Meter } from '@libraz/libcantus';\n * const result = Meter.tryParse('7/8');\n * result.ok ? result.value.pulsesPerBar : result.error.message; // 7\n * ```\n */\n static tryParse(text: string): ParseResult<Meter> {\n const parsed = tryParseTimeSignature(text);\n return parsed.ok ? { ok: true, value: new Meter(parsed.value) } : parsed;\n }\n\n /**\n * Wrap a plain time signature, as the meter module produces it.\n *\n * @param data The plain time signature.\n * @returns The wrapped meter.\n * @throws If the signature is not one the library accepts.\n */\n static fromData(data: TimeSignature): Meter {\n return new Meter(data);\n }\n\n /**\n * Rebuild a meter from its {@link Meter.toJSON} output.\n *\n * @param data The serialized time signature.\n * @returns The wrapped meter.\n * @throws If the signature is not one the library accepts.\n */\n static fromJSON(data: TimeSignature): Meter {\n return new Meter(data);\n }\n\n /** Beats in a bar, counted in denominator units: the 6 of 6/8. */\n get numerator(): number {\n return this.#ts.numerator;\n }\n\n /** The note value one unit is written as: the 8 of 6/8. */\n get denominator(): number {\n return this.#ts.denominator;\n }\n\n /** A copy of the felt-beat grouping, or undefined when the bar is ungrouped. */\n get grouping(): number[] | undefined {\n return this.#ts.grouping === undefined ? undefined : [...this.#ts.grouping];\n }\n\n /** A copy of the underlying plain time signature. */\n get data(): TimeSignature {\n return this.toJSON();\n }\n\n /**\n * Whether the meter is compound: its main pulses each divide into three, as\n * in 6/8, 9/8, or 12/8. A simple triple such as 3/4 is not compound, and\n * neither is a signature whose grouping selects the additive reading.\n */\n get isCompound(): boolean {\n return isCompound(this.#ts);\n }\n\n /** Length of a bar in quarter-note beats. */\n get beatsPerBar(): number {\n return beatsPerBar(this.#ts);\n }\n\n /** Main pulses (felt beats) in a bar: 2 in 6/8, 4 in 4/4. */\n get pulsesPerBar(): number {\n return pulsesPerBar(this.#ts);\n }\n\n /**\n * Length of one felt beat in quarter-note beats: a quarter note in simple\n * meters, a dotted quarter in compound ones.\n */\n get pulseBeats(): number {\n return pulseBeats(this.#ts);\n }\n\n /**\n * Render the signature as `'n/d'`, or as `'a+b+c/d'` when it carries an\n * additive grouping and one is asked for.\n *\n * @param opts Set `grouping: true` to render an additive grouping. A\n * grouping counted in main pulses has no additive spelling: one whose\n * groups are all the same length states the division the bare signature\n * already has and falls back to the plain form, and one whose groups differ\n * is refused rather than printed as a bar that weighs its pulses otherwise.\n * @returns The formatted signature.\n * @throws If `grouping: true` is asked of a grouping that no signature text\n * can spell: one counted in main pulses, on a compound numerator, whose\n * groups are not all the same length — 12/8 as `[1, 1, 2]`.\n * @example\n * ```ts\n * import { Meter } from '@libraz/libcantus';\n * Meter.of(7, 8, [2, 2, 3]).format({ grouping: true }); // '2+2+3/8'\n * Meter.of(12, 8, [1, 1, 1, 1]).format({ grouping: true }); // '12/8'\n * ```\n */\n format(opts: { grouping?: boolean } = {}): string {\n return formatTimeSignature(this.#ts, opts);\n }\n\n /**\n * Metric weight of a position within its bar, on a 0–3 scale: 3 the\n * downbeat, 2 a secondary strong pulse, 1 any other main pulse, and 0 an\n * off-pulse subdivision.\n *\n * @param beatInQuarters Position in quarter-note beats; a position past the\n * end of a bar is read in the bar it falls in.\n * @returns The metric weight (0–3).\n * @throws If the position is not finite.\n */\n weightAt(beatInQuarters: number): number {\n return metricWeight(beatInQuarters, this.#ts);\n }\n\n /**\n * Whether a position is metrically accented — a downbeat or a secondary\n * strong pulse.\n *\n * @param beatInQuarters Position in quarter-note beats.\n * @returns True on strong beats.\n * @throws If the position is not finite.\n */\n isStrongBeat(beatInQuarters: number): boolean {\n return isStrongBeat(beatInQuarters, this.#ts);\n }\n\n /**\n * Convert a position in quarter-note beats to a bar index and in-bar offset.\n *\n * @param beatInQuarters Position in quarter-note beats.\n * @returns The 0-based bar and the quarter-note offset within it.\n * @throws If the position is not finite.\n */\n barPositionAt(beatInQuarters: number): BarPosition {\n return beatToBarPosition(beatInQuarters, this.#ts);\n }\n\n /**\n * Render a position as the `bar.beat` a DAW or a score shows: 1-based bar,\n * 1-based felt beat.\n *\n * @param beatInQuarters Position in quarter-note beats.\n * @param decimals Digits of the fractional beat to keep.\n * @returns The formatted position in one of two forms: `bar.beat` on a felt\n * beat, e.g. `'3.2'` for bar 3, felt beat 2; and `bar.beat+fraction`\n * between felt beats, e.g. `'3.2+0.5'` halfway from the second felt beat to\n * the third. A reader of these strings has to take both, since most onsets\n * of an ordinary piece fall between pulses.\n * @throws If the position is not finite or `decimals` is not an integer in\n * 0..100.\n * @example\n * ```ts\n * import { Meter } from '@libraz/libcantus';\n * Meter.parse('6/8').formatPosition(7.5); // '3.2'\n * Meter.parse('6/8').formatPosition(8.25); // '3.2+0.5'\n * ```\n */\n formatPosition(beatInQuarters: number, decimals = 2): string {\n return formatBarPosition(beatInQuarters, this.#ts, decimals);\n }\n\n /**\n * Subdivide a span into equal tuplet durations — an eighth-note triplet is\n * `tuplet(1, 3)`.\n *\n * @param totalBeats Total span in quarter-note beats.\n * @param count Number of equal parts.\n * @returns `count` equal durations summing to `totalBeats`.\n * @throws If the span is negative or `count` is not a positive integer.\n */\n tuplet(totalBeats: number, count: number): number[] {\n return tuplet(totalBeats, count);\n }\n\n /**\n * Whether another meter is the same signature, grouping included.\n *\n * 6/8 and 3/4 fill a bar with the same six eighth notes and are not equal:\n * they group them differently, and every weight this class reports follows\n * the grouping.\n *\n * @param other The meter to compare with.\n * @returns True when numerator, denominator, and grouping all match.\n */\n equals(other: Meter): boolean {\n // The other meter is read through its public surface rather than its\n // private field: a bundler that emits two copies of this class — as a\n // CommonJS build without shared chunks does for the root and /model\n // entries — would otherwise throw on the brand check.\n const b = other.data;\n const grouping = this.#ts.grouping;\n if (grouping === undefined || b.grouping === undefined) {\n return (\n this.#ts.numerator === b.numerator &&\n this.#ts.denominator === b.denominator &&\n grouping === b.grouping\n );\n }\n return (\n this.#ts.numerator === b.numerator &&\n this.#ts.denominator === b.denominator &&\n grouping.length === b.grouping.length &&\n grouping.every((entry, index) => entry === b.grouping?.[index])\n );\n }\n\n /**\n * The plain time signature, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(meter)` from collapsing to `{}`. The grouping appears only\n * on a meter that carries one, which is the shape the meter module's own\n * parser produces.\n *\n * @returns A copy of the numerator, denominator, and grouping.\n */\n toJSON(): TimeSignature {\n return copyTimeSignature(this.#ts);\n }\n\n /**\n * The signature, so a template literal or a log line reads as the meter.\n *\n * @returns The plain form, e.g. `'6/8'`; ask {@link Meter.format} for the\n * additive one.\n */\n toString(): string {\n return this.format();\n }\n}\n","import type { MotifRelation } from '../analyze/melody/index.js';\nimport { melodicSimilarity, motifFromNotes, relateMotifs } from '../analyze/melody/index.js';\nimport type { ChordTimeline } from '../analyze/timeline/index.js';\nimport type { MeterLike } from '../core/meter/index.js';\nimport type { NoteEvent } from '../core/types.js';\nimport type {\n GenerationContextInput,\n MotifCell,\n MotifContour,\n MotifNote,\n MotifOptions,\n MotifTransform,\n} from '../generate/index.js';\nimport {\n developMotif,\n generateMotif,\n motifToNoteEvents,\n transformMotif,\n} from '../generate/index.js';\n// Not through the barrel: the span of a cell is the function layer's own\n// answer, shared so it is not restated here, and not a new public entry point.\nimport { cellSpan } from '../generate/motif/index.js';\nimport type { KeyLike, SpelledKeyLike } from '../theory/scale/index.js';\nimport { type ChordLike, toChordData } from '../theory/symbol/index.js';\nimport type { ScoreOptions } from './score.js';\nimport { Score } from './score.js';\nimport { assertDataObject, assertNoteEventArray, withoutNegativeZero } from './shared.js';\nimport type { Timeline } from './timeline.js';\n\n/**\n * How a motif is generated: what {@link MotifOptions} asks for, with the key\n * and the chord taken the way the rest of the class API takes them.\n */\nexport type MotifGenerateOptions = {\n /** The key the line is written in: a name, plain key data, or a {@link Key}. */\n key: KeyLike;\n /**\n * The chord the downbeats spell out, when the line is written over one: a\n * chord symbol, plain chord data, or a {@link Chord}. Without it no note is\n * pulled to a chord tone.\n */\n chord?: ChordLike | null;\n /** Length of the motif in bars of `ts`. */\n bars: number;\n /**\n * Meter the bars are counted in, which sets the bar length, in any form\n * that names one.\n *\n * @defaultValue 4/4\n */\n ts?: MeterLike;\n /**\n * Melodic contour shape the line follows.\n *\n * @defaultValue `'arch'`\n */\n contour?: MotifContour;\n /**\n * Probability in [0, 1] that a note is nudged by a single diatonic step;\n * sugar for the context's `complexity.ornament`, which wins where both are\n * given.\n *\n * @defaultValue 0\n */\n jitter?: number;\n /**\n * The generation context. Its `complexity.ornament` is the jitter and its\n * `seed` fixes which notes are nudged.\n *\n * @defaultValue `{ seed: 0 }`\n */\n ctx?: GenerationContextInput;\n};\n\n/** Defensive copy of one note, carrying only the fields a motif note holds. */\nfunction copyNote(note: MotifNote): MotifNote {\n return {\n pitch: withoutNegativeZero(note.pitch),\n startBeat: withoutNegativeZero(note.startBeat),\n durationBeat: withoutNegativeZero(note.durationBeat),\n };\n}\n\n/**\n * Defensive copy of a cell, its notes checked as they are copied.\n *\n * A note that never sounds is refused, which is the policy the transforms\n * themselves hold: a cell is written material rather than an imported track,\n * and a zero-length note in one would be tiled and transformed as though it\n * were a note.\n *\n * The notes keep the order they arrive in; a transform is what puts a cell into\n * time order, so a caller reading back exactly what it handed in is reading its\n * own array.\n *\n * The cell is checked as a whole before it is copied, so a cell holding more\n * notes than the transforms are budgeted to work on is refused here rather than\n * at the first transform asked for.\n */\nfunction copyCell(cell: MotifCell): MotifCell {\n assertDataObject(cell, 'motif cell');\n return { notes: assertNoteEventArray(cell.notes, 'motif notes').map(copyNote) };\n}\n\n/** The chord data a {@link MotifGenerateOptions.chord} value names, if any. */\nfunction chordFrom(chord: ChordLike | null | undefined): MotifOptions['chord'] {\n return chord === undefined || chord === null ? chord : toChordData(chord);\n}\n\n/**\n * A short melodic cell, and the transformations that make a piece out of one.\n *\n * A motif is the smallest thing a composer works with: a handful of notes that\n * come back inverted, in retrograde, a step higher, twice as slow. The library\n * generates one and transforms one, but every step hands back a bare cell that\n * has to be named again on the way into the next, and the key travels beside it\n * by hand. A `Motif` carries the cell, so a subject and its answer are two\n * expressions rather than two variables.\n *\n * The cell holds notes and nothing else: the key it was written in is not part\n * of it, since the same figure is worth restating in another key, and the\n * members that need one are given it.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Motif } from '@libraz/libcantus';\n * const subject = Motif.generate({ key: 'C major', bars: 1 });\n * subject.transform('invert').relateTo(subject)?.kind; // 'inversion'\n * ```\n */\nexport class Motif {\n readonly #cell: MotifCell;\n\n /**\n * Wrap a plain motif cell.\n *\n * @param cell The notes of the cell; copied, never retained.\n * @throws If a note carries a value the transforms cannot hold.\n */\n constructor(cell: MotifCell) {\n this.#cell = copyCell(cell);\n }\n\n /**\n * Generate a seed motif.\n *\n * The line follows the requested contour in diatonic steps from the tonic,\n * snapped to the key; with a chord in hand, the notes landing on bar\n * downbeats are pulled to the nearest chord tone.\n *\n * @param opts Key, chord, length, contour, jitter and context; see\n * {@link MotifGenerateOptions}.\n * @returns The generated motif.\n * @throws If the key or the chord names none, or a dial is outside [0, 1].\n * @example\n * ```ts\n * import { Motif } from '@libraz/libcantus';\n * const motif = Motif.generate({ key: 'C major', bars: 2, contour: 'ascending' });\n * motif.notes.length; // 4\n * ```\n */\n static generate(opts: MotifGenerateOptions): Motif {\n return new Motif(generateMotif({ ...opts, chord: chordFrom(opts.chord) }));\n }\n\n /**\n * Read a run of notes as a motif.\n *\n * This is how a caller names a cell it already has — a subject lifted out of\n * a score, a phrase a player typed in. Only the fields a motif note carries\n * are kept, so notes that arrived from a score leave their dynamics behind.\n *\n * @param notes The cell, in the order the transforms should read it.\n * @returns The motif.\n * @throws If a note carries a value the transforms cannot hold.\n */\n static fromNotes(notes: readonly NoteEvent[]): Motif {\n return new Motif({ notes: [...notes] });\n }\n\n /** Rebuild a motif from the plain data {@link Motif.data} hands out. */\n static fromData(cell: MotifCell): Motif {\n return new Motif(cell);\n }\n\n /** Rebuild a motif from its {@link Motif.toJSON} output. */\n static fromJSON(cell: MotifCell): Motif {\n return new Motif(cell);\n }\n\n /** The notes of the cell, in the order the transforms read them. */\n get notes(): MotifNote[] {\n return this.#cell.notes.map(copyNote);\n }\n\n /** Where the cell stops sounding, measured from its own first onset. */\n get totalBeats(): number {\n return cellSpan(this.#cell);\n }\n\n /** A copy of the underlying plain cell. */\n get data(): MotifCell {\n return { notes: this.#cell.notes.map(copyNote) };\n }\n\n /**\n * The cell put through one of the classical transformations.\n *\n * `invert` reflects the pitches about the earliest note and `retrograde`\n * mirrors the onsets about the cell's span, both self-inverse; `augment` and\n * `diminish` scale the note values by `amount` and its reciprocal;\n * `transposeChromatic` moves by semitones; `transposeDiatonic` and `sequence`\n * move by scale degrees with a key in hand, and by semitones without one.\n *\n * The result's notes run in time order whichever way the source cell was\n * written, so an inversion of a retrograde reflects about the note that now\n * sounds first.\n *\n * @param kind The transformation.\n * @param amount Semitones, scale degrees, or the time factor, as the\n * transformation reads it.\n * @param key Key context for the diatonic transformations: a name, plain key\n * data, or a {@link Key}.\n * @returns The transformed motif.\n * @throws If a transformed pitch would leave the MIDI range.\n * @example\n * ```ts\n * import { Motif } from '@libraz/libcantus';\n * const motif = Motif.fromNotes([\n * { pitch: 60, startBeat: 0, durationBeat: 1 },\n * { pitch: 62, startBeat: 1, durationBeat: 1 },\n * ]);\n * motif.transform('transposeDiatonic', 1, 'C major').notes[0]?.pitch; // 62\n * ```\n */\n transform(kind: MotifTransform, amount?: number, key?: KeyLike): Motif {\n return new Motif(transformMotif(this.#cell, kind, amount, key));\n }\n\n /**\n * The cell laid across a span and snapped to the harmony under it.\n *\n * The cell is tiled back to back to fill the bars asked for; the notes\n * carrying structural weight are pulled to the nearest chord tone of the\n * segment sounding there, and the ones between them are kept in the key.\n *\n * @param timeline The harmony to snap against, as a {@link Timeline} or the\n * plain chord timeline the analysis layer hands out.\n * @param key The key the passing notes are kept in.\n * @param bars How many bars to fill.\n * @param ts Meter the bars are counted in, in any form that names one. A\n * motif carries no meter of its own — it is a run of notes — so there is\n * nothing to fall back on, and a development laid on the wrong bar length\n * drifts off the part it plays under.\n * @returns The developed motif.\n * @throws If the bar count is not a positive integer.\n */\n develop(timeline: Timeline | ChordTimeline, key: KeyLike, bars: number, ts: MeterLike): Motif {\n // Read through the public surface rather than by `instanceof`, so a\n // timeline built by a second copy of the module develops like any other.\n const chords = 'chordTimeline' in timeline ? timeline.chordTimeline : timeline;\n return new Motif(developMotif(this.#cell, chords, key, bars, ts));\n }\n\n /**\n * How this motif stands to another: the transformation that turns one into\n * the other, named.\n *\n * @param other The statement to name against this one.\n * @param key Key context for the tonal reading. Without one an answer holding\n * only diatonically is left unnamed unless its interval pattern also fits\n * the retrograde family, in which case it is named there; a motif carries no\n * key of its own, so this is the only way to have the tonal reading offered.\n * @returns The relation, or null when the two stand in none.\n */\n relateTo(other: Motif, key?: SpelledKeyLike): MotifRelation | null {\n return relateMotifs(motifFromNotes(this.#cell.notes), motifFromNotes(other.notes), key);\n }\n\n /**\n * How alike two lines are, in [0, 1].\n *\n * What {@link Motif.relateTo} answers null for still scores here: this is the\n * measure for a variant that adds a passing note or drops one, rather than\n * for the exact transformations.\n *\n * @param other The line to compare with.\n * @returns The likeness: 1 for the same line, a transposition of it included.\n */\n similarityTo(other: Motif): number {\n return melodicSimilarity(this.#cell.notes, other.notes);\n }\n\n /**\n * The cell as a score, so it reaches the rest of the class API.\n *\n * @param opts The meter, tempo and key to read the notes against; see\n * {@link ScoreOptions}.\n * @returns The score holding the cell.\n */\n toScore(opts?: ScoreOptions): Score {\n return Score.of(motifToNoteEvents(this.#cell), opts);\n }\n\n /**\n * Whether another motif holds the same notes in the same order.\n *\n * The comparison is made through the other motif's public data, so two\n * motifs built by different copies of the module still compare. The order is\n * part of it: the transformations read the first note of the cell as its\n * pivot, so two cells sounding alike but read from different ends are not\n * the same motif.\n *\n * @param other The motif to compare.\n * @returns True when the cells hold the same notes in the same order.\n */\n equals(other: Motif): boolean {\n const theirs = other.data;\n return (\n this.#cell.notes.length === theirs.notes.length &&\n this.#cell.notes.every((note, index) => sameNote(note, theirs.notes[index]))\n );\n }\n\n /** The plain form of the cell, for `JSON.stringify`. */\n toJSON(): MotifCell {\n return this.data;\n }\n}\n\n/** Whether two notes sound the same pitch over the same stretch. */\nfunction sameNote(note: MotifNote, other: MotifNote | undefined): boolean {\n return (\n other !== undefined &&\n note.pitch === other.pitch &&\n note.startBeat === other.startBeat &&\n note.durationBeat === other.durationBeat\n );\n}\n","import type { MeterLike, TimeSignature } from '../core/meter/index.js';\nimport { meterAt, toMeterData } from '../core/meter/index.js';\nimport { assertRange } from '../core/validation/index.js';\nimport type {\n DeformOptions,\n GenerationContextInput,\n GridEvent,\n RhythmEvent,\n RhythmOptions,\n} from '../generate/index.js';\nimport {\n deform,\n doubleTime,\n generateRhythm,\n halfTime,\n ornamentBy,\n resolveContext,\n rhythmDensity,\n rhythmToNoteEvents,\n STEP_BEATS,\n syncopate,\n thin,\n withinCeiling,\n} from '../generate/index.js';\nimport { Score } from './score.js';\nimport {\n assertDataArray,\n assertDataObject,\n assertDataObjects,\n copyTimeSignature,\n withoutNegativeZero,\n} from './shared.js';\n\n/** The plain form a {@link Rhythm} hands out and is rebuilt from. */\nexport type RhythmData = {\n /** The onsets, in time order, measured in quarter-note beats. */\n events: RhythmEvent[];\n /** The meter the onsets are counted in. */\n ts: TimeSignature;\n};\n\n/** What {@link Rhythm.deform} does to a pattern beyond what the dials say. */\nexport type RhythmDeformOptions = {\n /**\n * Stretch or compress the pattern before the dials are applied, as\n * {@link DeformOptions.rate} does.\n */\n rate?: 'straight' | 'half' | 'double';\n /**\n * Which onsets count as decoration, for the ornament dial. A rhythm carries\n * no dynamics of its own, so what counts is the caller's reading of where the\n * onsets fall.\n */\n isOrnament?: (event: RhythmEvent) => boolean;\n};\n\n/**\n * The loudness every onset enters the sixteenth grid at.\n *\n * The transforms play an added note softer than the one it follows, which is a\n * statement about dynamics; a rhythm is onsets alone, so they all enter alike\n * and the scaling is dropped again on the way back.\n */\nconst GRID_VELOCITY = 1;\n\n/** The part name the pattern's draws are addressed under, as the generator's are. */\nconst PART = 'rhythm';\n\n/** A grid onset that remembers the pattern onset it was built from. */\ntype SourcedGridEvent = GridEvent & { source: RhythmEvent };\n\n/** Defensive copy of one onset, checked as it is copied. */\nfunction copyEvent(event: RhythmEvent, name: string): RhythmEvent {\n return {\n position: withoutNegativeZero(\n assertRange(event.position, 0, Number.MAX_SAFE_INTEGER, `${name}.position`),\n ),\n duration: withoutNegativeZero(\n assertRange(event.duration, 0, Number.MAX_SAFE_INTEGER, `${name}.duration`),\n ),\n };\n}\n\n/**\n * The onsets checked and copied, in time order.\n *\n * A rhythm is asked what falls where rather than what arrived first, so the\n * order is settled here: every transform below, and every `equals` between two\n * patterns holding the same onsets, then reads the same sequence.\n */\nfunction copyEvents(events: readonly RhythmEvent[], name: string): RhythmEvent[] {\n return assertDataObjects<RhythmEvent>(events, name)\n .map((event, index) => copyEvent(event, `${name}[${index}]`))\n .sort((a, b) => a.position - b.position || a.duration - b.duration);\n}\n\n/** Defensive copy of plain rhythm data, with every part validated. */\nfunction copyRhythm(data: RhythmData): RhythmData {\n assertDataObject(data, 'rhythm data');\n return {\n events: copyEvents(data.events, 'rhythm events'),\n ts: copyTimeSignature(data.ts, 'rhythm ts'),\n };\n}\n\n/** Where the pattern stops: the furthest point any onset sounds to. */\nfunction spanOf(events: readonly RhythmEvent[]): number {\n return events.reduce((end, event) => Math.max(end, event.position + event.duration), 0);\n}\n\n/**\n * The pattern's onsets on the sixteenth grid the transforms are written for.\n *\n * A position that is not a whole sixteenth — a triplet, anything generated at\n * another subdivision — keeps its exact place and is read as the off-grid, and\n * so weakest, position it is.\n */\nfunction toGrid(events: readonly RhythmEvent[]): SourcedGridEvent[] {\n return events.map((event) => ({\n step: event.position / STEP_BEATS,\n velocity: GRID_VELOCITY,\n source: event,\n }));\n}\n\n/**\n * The onsets a transform returned, read back as a pattern over the same span.\n *\n * Durations are re-read from the onsets rather than carried through the\n * transform, exactly as the generator writes them: each onset sounds until the\n * next, and the last to the end of the span the pattern covered before the\n * transform. Two onsets landing on one position are one onset, since a rhythm\n * has nothing to tell them apart with.\n */\nfunction fromGrid(events: readonly GridEvent[], spanBeats: number): RhythmEvent[] {\n const positions = [...new Set(events.map((event) => event.step * STEP_BEATS))].sort(\n (a, b) => a - b,\n );\n return positions.map((position, index) => ({\n position,\n duration: (positions[index + 1] ?? spanBeats) - position,\n }));\n}\n\n/**\n * A pattern of onsets over a meter, and the transformations that reshape one.\n *\n * The library generates a rhythm as a bare array and deforms one with a family\n * of functions — thinning, syncopating, halving and doubling the rate — that\n * each take an array and hand one back. They are shaped to chain and cannot:\n * every step has to name the pattern again, and the meter it is counted in\n * travels beside it by hand. A `Rhythm` holds the two together, so the family\n * reads as the chain it always was.\n *\n * The transformations are written against a sixteenth grid, so the onsets are\n * converted to it and read back afterwards. A rhythm carries no dynamics, and\n * the softer stroke a transform gives an added note is not part of what comes\n * back.\n *\n * @category Class API\n * @example\n * ```ts\n * import { parseTimeSignature } from '@libraz/libcantus';\n * import { Rhythm } from '@libraz/libcantus';\n * const rhythm = Rhythm.generate(parseTimeSignature('4/4'), { ctx: { seed: 42 } });\n * rhythm.syncopate(0.3).toScore(38).notes.length >= rhythm.events.length; // true\n * ```\n */\nexport class Rhythm {\n readonly #data: RhythmData;\n\n /**\n * Wrap plain rhythm data.\n *\n * @param data The onsets and the meter they are counted in; copied, never\n * retained.\n * @throws If an onset or the meter carries a value a pattern cannot hold.\n */\n constructor(data: RhythmData) {\n this.#data = copyRhythm(data);\n }\n\n /**\n * Generate a pattern over a meter.\n *\n * @param ts The time signature the bars are counted in, in any form that\n * names one; a meter map is read as the signature it opens in.\n * @param opts Length, grid resolution and the context; see\n * {@link RhythmOptions}. The context's `complexity.rhythmic` is the onset\n * density, and its `seed` fixes which grid slots are taken.\n * @returns The generated pattern.\n * @example\n * ```ts\n * import { Rhythm } from '@libraz/libcantus';\n * const rhythm = Rhythm.generate('4/4', {\n * bars: 2,\n * ctx: { seed: 7, complexity: { rhythmic: 0.6 } },\n * });\n * rhythm.totalBeats; // 8\n * ```\n */\n static generate(ts: MeterLike, opts?: RhythmOptions): Rhythm {\n // Read once, here: the pattern and the meter it is counted in are stored\n // together, so both sides read the signature the caller named.\n const meter = meterAt(0, toMeterData(ts, 'ts'));\n return new Rhythm({ events: generateRhythm(meter, opts), ts: meter });\n }\n\n /**\n * Build a pattern from onsets that already exist.\n *\n * The meter is asked for rather than assumed. A pattern in 6/8 read as 4/4\n * answers every metric question — which beats are strong, where the bars\n * fall, how dense it is — on the wrong pulse, and nothing downstream can tell\n * that reading from a meter the caller meant. Its two siblings,\n * {@link Rhythm.generate} and `generateRhythm`, ask for it the same way.\n *\n * @param events The onsets, in any order.\n * @param ts The meter they are counted in, in any form that names one.\n * @returns The pattern.\n * @throws If the meter names no signature, or an onset carries a value a\n * pattern cannot hold.\n */\n static of(events: readonly RhythmEvent[], ts: MeterLike): Rhythm {\n return new Rhythm({\n events: [...assertDataArray<RhythmEvent>(events, 'rhythm events')],\n ts: meterAt(0, toMeterData(ts, 'ts')),\n });\n }\n\n /** Rebuild a pattern from the plain data {@link Rhythm.data} hands out. */\n static fromData(data: RhythmData): Rhythm {\n return new Rhythm(data);\n }\n\n /** Rebuild a pattern from its {@link Rhythm.toJSON} output. */\n static fromJSON(data: RhythmData): Rhythm {\n return new Rhythm(data);\n }\n\n /** The onsets, in time order. */\n get events(): RhythmEvent[] {\n return this.#data.events.map((event) => ({ ...event }));\n }\n\n /** The meter the onsets are counted in. */\n get ts(): TimeSignature {\n return copyTimeSignature(this.#data.ts, 'rhythm ts');\n }\n\n /** Where the pattern stops: the furthest point any onset sounds to. */\n get totalBeats(): number {\n return spanOf(this.#data.events);\n }\n\n /** A copy of the underlying plain data. */\n get data(): RhythmData {\n return {\n events: this.#data.events.map((event) => ({ ...event })),\n ts: copyTimeSignature(this.#data.ts, 'rhythm ts'),\n };\n }\n\n /**\n * How busy the pattern is: the mean number of onsets per bar.\n *\n * @returns The onset count divided by the number of bars it spans.\n */\n density(): number {\n return rhythmDensity(this.#data.events, this.#data.ts);\n }\n\n /**\n * Drop the onsets carrying the least of the metre.\n *\n * The metre is the pattern's own: the ranks are read from {@link Rhythm.ts},\n * so a pattern in 6/8 keeps its dotted-quarter pulses and one in 3/4 keeps its\n * three-beat downbeats rather than the beats a four-beat bar would have.\n *\n * @param amount How much to thin, in [0, 1]; at 0 nothing goes, and a full\n * turn leaves the downbeats alone.\n * @returns The thinned pattern.\n * @throws If the amount is outside [0, 1].\n */\n thin(amount: number): Rhythm {\n return this.#withGrid(thin(toGrid(this.#data.events), amount, this.#data.ts));\n }\n\n /**\n * Anticipate beats, one sixteenth early.\n *\n * The beats anticipated are the ones {@link Rhythm.ts} counts as main pulses\n * or stronger, so a pattern is not syncopated against accents its own meter\n * does not have. The anticipations are added rather than displaced, so raising\n * the amount only ever adds onsets and the ones already sounding stay where\n * they are.\n *\n * @param amount How much syncopation, in [0, 1].\n * @param ctx The context, or the seed alone; it fixes which beats are\n * anticipated.\n * @returns The syncopated pattern.\n * @throws If the amount is outside [0, 1].\n */\n syncopate(amount: number, ctx?: GenerationContextInput): Rhythm {\n return this.#withGrid(\n syncopate(\n toGrid(this.#data.events),\n { amount, ts: this.#data.ts },\n resolveContext(ctx).part(PART),\n ),\n );\n }\n\n /**\n * Compress the pattern to half its length and play it twice.\n *\n * The span is the pattern's own, so it stays as full as it was.\n *\n * @returns The compressed pattern.\n */\n doubleTime(): Rhythm {\n return this.#withGrid(doubleTime(toGrid(this.#data.events), this.#spanSteps()));\n }\n\n /**\n * Stretch the pattern to twice its length: everything falls half as often.\n *\n * Onsets stretched past the span are dropped, since the span is the span\n * however the pattern is felt.\n *\n * @returns The stretched pattern.\n */\n halfTime(): Rhythm {\n return this.#withGrid(halfTime(toGrid(this.#data.events), this.#spanSteps()));\n }\n\n /**\n * Keep as much decoration as the ornament dial asks for.\n *\n * Each decorated onset survives on its own draw, so raising the amount brings\n * more of them back without disturbing the ones already sounding. Onsets the\n * predicate does not claim are untouched.\n *\n * @param isOrnament Which onsets count as decoration.\n * @param amount The ornament dial, in [0, 1].\n * @param ctx The context, or the seed alone; it fixes which decoration stays.\n * @returns The pattern with the surviving decoration.\n * @throws If the amount is outside [0, 1].\n */\n ornamentBy(\n isOrnament: (event: RhythmEvent) => boolean,\n amount: number,\n ctx?: GenerationContextInput,\n ): Rhythm {\n return this.#withGrid(\n ornamentBy(\n toGrid(this.#data.events),\n (grid) => isOrnament(grid.source),\n amount,\n resolveContext(ctx).part(PART),\n ),\n );\n }\n\n /**\n * Apply the complexity dials to the pattern in one pass.\n *\n * The dials are read from the context, which is where they live for every\n * generator: `complexity.rhythmic` below its neutral middle thins the pattern\n * and above it syncopates, and `complexity.ornament` decides how much of what\n * `isOrnament` claims survives. The span the rate is measured against is the\n * pattern's own.\n *\n * @param opts The rate, and which onsets are decoration; see\n * {@link RhythmDeformOptions}.\n * @param ctx The context, or the seed alone; it carries the dials.\n * @returns The deformed pattern.\n * @throws If a dial is outside [0, 1].\n */\n deform(opts?: RhythmDeformOptions, ctx?: GenerationContextInput): Rhythm {\n const resolved = resolveContext(ctx);\n const isOrnament = opts?.isOrnament;\n const options: DeformOptions = {\n rhythmic: resolved.rhythmic,\n ornament: resolved.ornament,\n rate: opts?.rate,\n spanSteps: this.#spanSteps(),\n ts: this.#data.ts,\n // The transform hands the predicate the events it was given, which carry\n // the onset each was built from; the parameter is declared over the bare\n // grid event the rule reads, so the field is named back here.\n isOrnament:\n isOrnament === undefined\n ? undefined\n : (grid) => isOrnament((grid as SourcedGridEvent).source),\n };\n return this.#withGrid(deform(toGrid(this.#data.events), options, resolved.part(PART)));\n }\n\n /**\n * Whether one player can sustain the pattern at the context's tempo.\n *\n * The ceiling is measured against the closest pair of onsets, which is what\n * actually stops a hand. A context naming no tempo or no ceiling has nothing\n * to measure against, and the pattern passes.\n *\n * @param ctx The context, or the seed alone; its `bpm` and its\n * `complexity.difficulty` are what the answer is read from.\n * @returns True when the pattern is inside the ceiling.\n */\n withinCeiling(ctx?: GenerationContextInput): boolean {\n const resolved = resolveContext(ctx);\n return withinCeiling(toGrid(this.#data.events), resolved.bpm, resolved.difficulty);\n }\n\n /**\n * The pattern as sounding notes at one pitch, in its own meter.\n *\n * This is where a rhythm reaches the rest of the class API: the score it\n * hands back can be humanized, grooved, analysed, or written out like any\n * other line.\n *\n * @param pitch The MIDI pitch to give every onset.\n * @param velocity Velocity for every onset; a mezzo-forte 96 by default.\n * @returns The score holding the pattern.\n * @throws If the pitch or the velocity is not a whole MIDI value in [0, 127];\n * both are the numbers a note event carries, and a fractional one is not a\n * note anything downstream can sound.\n * @example\n * ```ts\n * import { parseTimeSignature } from '@libraz/libcantus';\n * import { Rhythm } from '@libraz/libcantus';\n * const score = Rhythm.generate(parseTimeSignature('4/4')).toScore(38);\n * score.notes.every((note) => note.pitch === 38); // true\n * ```\n */\n toScore(pitch: number, velocity?: number): Score {\n return Score.of(rhythmToNoteEvents(this.#data.events, pitch, velocity), {\n meters: this.#data.ts,\n });\n }\n\n /**\n * Whether another pattern holds the same onsets in the same meter.\n *\n * The comparison is made through the other pattern's public data, so two\n * patterns built by different copies of the module still compare.\n *\n * @param other The pattern to compare.\n * @returns True when the onsets and the meter match.\n */\n equals(other: Rhythm): boolean {\n const theirs = other.data;\n const mine = this.#data;\n return (\n mine.events.length === theirs.events.length &&\n mine.events.every((event, index) => sameEvent(event, theirs.events[index])) &&\n sameSignature(mine.ts, theirs.ts)\n );\n }\n\n /** The plain form of the pattern, for `JSON.stringify`. */\n toJSON(): RhythmData {\n return this.data;\n }\n\n /** The pattern's span as a count of sixteenths, for the transforms. */\n #spanSteps(): number {\n return spanOf(this.#data.events) / STEP_BEATS;\n }\n\n /** The same meter carrying the onsets a transform returned. */\n #withGrid(events: readonly GridEvent[]): Rhythm {\n return new Rhythm({\n events: fromGrid(events, spanOf(this.#data.events)),\n ts: this.#data.ts,\n });\n }\n}\n\n/** Whether two onsets fall at the same place for the same length. */\nfunction sameEvent(event: RhythmEvent, other: RhythmEvent | undefined): boolean {\n return (\n other !== undefined && event.position === other.position && event.duration === other.duration\n );\n}\n\n/** Whether two signatures name the same meter, grouping included. */\nfunction sameSignature(ts: TimeSignature, other: TimeSignature): boolean {\n const grouping = ts.grouping ?? [];\n const theirs = other.grouping ?? [];\n return (\n ts.numerator === other.numerator &&\n ts.denominator === other.denominator &&\n grouping.length === theirs.length &&\n grouping.every((entry, index) => entry === theirs[index])\n );\n}\n","import {\n beatsToSeconds,\n beatsToTicks,\n durationToSeconds,\n secondsToBeats,\n ticksToBeats,\n} from '../core/tempo/index.js';\nimport { assertRange } from '../core/validation/index.js';\nimport { assertDataObject } from './shared.js';\n\n/**\n * Upper bound on a tempo, the bound the tempo module and the generators\n * accept. A faster marking is a notation of a slower pulse, not a distinct\n * tempo.\n */\nconst MAX_BPM = 1000;\n\n/**\n * Lower bound on a tempo, the bound the tempo module accepts. One beat lasts\n * ten minutes here; anything slower is a corrupt or mis-scaled value rather\n * than a marking, and the conversions it feeds would overflow to infinity.\n */\nconst MIN_BPM = 0.1;\n\n/**\n * A constant tempo as plain data: quarter-note beats per minute.\n *\n * @category Class API\n */\nexport type TempoData = {\n /** Quarter-note beats per minute. */\n bpm: number;\n};\n\n/**\n * An immutable constant tempo, in quarter-note beats per minute, and the\n * conversions it settles: beats to wall-clock seconds and back, and beats to\n * MIDI ticks and back.\n *\n * One tempo, not a piece's tempo over time: a piece that changes tempo is\n * described by a tempo map, which the tempo module's own functions read.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Tempo } from '@libraz/libcantus';\n * Tempo.of(120).secondsAt(16); // 8\n * ```\n */\nexport class Tempo {\n readonly #bpm: number;\n\n private constructor(bpm: number) {\n this.#bpm = assertRange(bpm, MIN_BPM, MAX_BPM, 'bpm');\n }\n\n /**\n * The one-event tempo map every conversion here is measured against.\n *\n * Built on read rather than held, so nothing outside the class can reach the\n * array the conversions run over.\n */\n get #map(): readonly { startBeat: number; bpm: number }[] {\n return [{ startBeat: 0, bpm: this.#bpm }];\n }\n\n /**\n * Build a tempo from a beats-per-minute marking.\n *\n * @param bpm Quarter-note beats per minute.\n * @returns The tempo.\n * @throws If the marking is not a positive, finite number the library holds.\n */\n static of(bpm: number): Tempo {\n return new Tempo(bpm);\n }\n\n /**\n * Wrap a plain tempo value.\n *\n * @param data The plain tempo.\n * @returns The wrapped tempo.\n * @throws If the marking is not a positive, finite number the library holds.\n */\n static fromData(data: TempoData): Tempo {\n return new Tempo(assertDataObject<TempoData>(data, 'tempo data').bpm);\n }\n\n /**\n * Rebuild a tempo from its {@link Tempo.toJSON} output.\n *\n * @param data The serialized tempo.\n * @returns The wrapped tempo.\n * @throws If the marking is not a positive, finite number the library holds.\n */\n static fromJSON(data: TempoData): Tempo {\n return new Tempo(assertDataObject<TempoData>(data, 'tempo data').bpm);\n }\n\n /** Quarter-note beats per minute. */\n get bpm(): number {\n return this.#bpm;\n }\n\n /** A copy of the underlying plain tempo value. */\n get data(): TempoData {\n return this.toJSON();\n }\n\n /**\n * Wall-clock seconds from the downbeat to a position.\n *\n * A position before the downbeat reports negative elapsed time: a pickup\n * sounds before it, and asking when it sounds is a fair question.\n *\n * @param beat Position in quarter-note beats.\n * @returns Elapsed seconds, 0 at beat 0 and negative before it.\n * @throws If the position is not finite.\n */\n secondsAt(beat: number): number {\n return beatsToSeconds(beat, this.#map);\n }\n\n /**\n * The position reached after a number of seconds — the inverse of\n * {@link Tempo.secondsAt}.\n *\n * @param seconds Elapsed seconds from the downbeat; negative for a position\n * before it, such as a pickup.\n * @returns The position in quarter-note beats.\n * @throws If the elapsed time is not finite.\n * @example\n * ```ts\n * import { Tempo } from '@libraz/libcantus';\n * Tempo.of(90).beatAtSeconds(4); // 6\n * ```\n */\n beatAtSeconds(seconds: number): number {\n return secondsToBeats(seconds, this.#map);\n }\n\n /**\n * Duration in seconds of a span of beats.\n *\n * The tempo is constant, so the span is measured from the downbeat: where it\n * begins cannot change how long it lasts.\n *\n * @param lengthBeats How long the span lasts, in quarter-note beats.\n * @returns The span's duration in seconds.\n * @throws If the length is negative or not finite.\n */\n secondsOf(lengthBeats: number): number {\n return durationToSeconds(0, lengthBeats, this.#map);\n }\n\n /**\n * Convert quarter-note beats to MIDI ticks, rounded to the nearest tick.\n *\n * @param beat Position or length in quarter-note beats.\n * @param ppq Pulses (ticks) per quarter note, e.g. 96, 480, or 960.\n * @returns The whole tick count, negative before the first downbeat.\n * @throws If the position is not finite or `ppq` is not a positive integer.\n */\n ticksAt(beat: number, ppq: number): number {\n return beatsToTicks(beat, ppq);\n }\n\n /**\n * Convert MIDI ticks to quarter-note beats.\n *\n * @param ticks Whole tick count, negative before the first downbeat.\n * @param ppq Pulses (ticks) per quarter note, e.g. 96, 480, or 960.\n * @returns The position or length in quarter-note beats.\n * @throws If `ticks` is not an integer or `ppq` is not a positive integer.\n */\n beatAtTicks(ticks: number, ppq: number): number {\n return ticksToBeats(ticks, ppq);\n }\n\n /**\n * Whether another tempo carries the same marking.\n *\n * @param other The tempo to compare with.\n * @returns True when both name the same beats per minute.\n */\n equals(other: Tempo): boolean {\n // The other tempo is read through its public accessor rather than its\n // private field: a bundler that emits two copies of this class — as a\n // CommonJS build without shared chunks does for the root and /model\n // entries — would otherwise throw on the brand check.\n return this.#bpm === other.bpm;\n }\n\n /**\n * The plain tempo value, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(tempo)` from collapsing to `{}`.\n *\n * @returns A copy of the marking.\n */\n toJSON(): TempoData {\n return { bpm: this.#bpm };\n }\n\n /**\n * The marking, so a template literal or a log line reads as the tempo.\n *\n * @returns The marking, e.g. `'120 bpm'`.\n */\n toString(): string {\n return `${this.#bpm} bpm`;\n }\n}\n","import type { NoteLike } from '../core/pitch/index.js';\nimport { noteToMidi, toNoteData } from '../core/pitch/index.js';\nimport type { TuningTable } from '../core/tuning/index.js';\nimport {\n centsBetweenFreq,\n centsFromNearestStep,\n centsOfSteps,\n centsToRatio,\n edo,\n frequencyOf,\n justDeviationCents,\n nearestStep,\n ratioToCents,\n stepOf,\n stepsOfCents,\n TWELVE_TET,\n} from '../core/tuning/index.js';\nimport { assertFiniteNumber } from '../core/validation/index.js';\nimport { assertDataObject } from './shared.js';\n\n/**\n * An immutable equal temperament: a reference pitch and a number of equal\n * divisions of the octave, with the conversions of the tuning module bound to\n * it. A thin convenience wrapper over a plain {@link TuningTable}.\n *\n * Every conversion still takes a temperament of its own, defaulting to this\n * one, so nothing the tuning functions offer is out of reach from the class —\n * two temperaments can be read from a single object.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Tuning.edo(19).divisions; // 19\n * Tuning.twelveTet().frequencyOf('A4'); // 440\n * ```\n */\nexport class Tuning {\n readonly #table: TuningTable;\n\n private constructor(table: TuningTable) {\n this.#table = table;\n }\n\n /**\n * Wrap a plain tuning table.\n *\n * Every field is read off the table, so a deserialized or hand-written one\n * cannot enter carrying a division count or a reference frequency no\n * frequency follows from. None of the three has a default here, unlike\n * {@link Tuning.edo}: a table that lost its reference frequency on the way\n * through storage is refused rather than quietly retuned to A=440.\n *\n * @param table The plain tuning table.\n * @returns The wrapped tuning.\n * @throws If a field is missing, the divisions are not a positive integer,\n * the reference frequency is not a finite positive number, or the reference\n * step is not finite.\n * @example\n * ```ts\n * import { TWELVE_TET, Tuning } from '@libraz/libcantus';\n * Tuning.of(TWELVE_TET).divisions; // 12\n * ```\n */\n static of(table: TuningTable): Tuning {\n // The tuning module's own constructor does the checking and returns a\n // fresh table, so a caller's object cannot become library state.\n const given = assertDataObject<TuningTable>(table, 'tuning table');\n // The fields are checked before edo() is handed them: its reference\n // frequency and step are optional positional arguments, so a missing one\n // would take the library's default instead of naming the field it is.\n assertFiniteNumber(given.divisions, 'tuning table.divisions');\n assertFiniteNumber(given.refFreq, 'tuning table.refFreq');\n assertFiniteNumber(given.refStep, 'tuning table.refStep');\n return new Tuning(edo(given.divisions, given.refFreq, given.refStep));\n }\n\n /**\n * Build an equal temperament with `divisions` divisions of the octave.\n *\n * @param divisions Divisions of the octave (e.g. 19, 24, 31).\n * @param refFreq Reference frequency in Hz; 440 by default.\n * @param refStep Step index of the reference; 69 by default, the MIDI number\n * of A4.\n * @returns The tuning.\n * @throws If the divisions are not a positive integer, the reference\n * frequency is not a finite positive number, or the reference step is not\n * finite. A negative or fractional reference step is accepted: it is what a\n * tuner reading or a pitch-bend calibration lands on.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Math.round(Tuning.edo(19).centsOfSteps(1)); // 63\n * ```\n */\n static edo(divisions: number, refFreq?: number, refStep?: number): Tuning {\n return new Tuning(edo(divisions, refFreq, refStep));\n }\n\n /**\n * Standard twelve-tone equal temperament, A4 (MIDI 69) = 440 Hz.\n *\n * @returns The tuning in which a step index is an ordinary MIDI number.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Tuning.twelveTet().stepOf(440); // 69\n * ```\n */\n static twelveTet(): Tuning {\n return Tuning.of(TWELVE_TET);\n }\n\n /**\n * Rebuild a tuning from the plain table {@link Tuning.data} hands out.\n *\n * @param data The plain tuning table.\n * @returns The wrapped tuning.\n * @throws If the table describes no temperament; see {@link Tuning.of}.\n */\n static fromData(data: TuningTable): Tuning {\n return Tuning.of(data);\n }\n\n /**\n * Rebuild a tuning from its {@link Tuning.toJSON} output.\n *\n * @param data The serialized tuning table.\n * @returns The wrapped tuning.\n * @throws If the table describes no temperament; see {@link Tuning.of}.\n */\n static fromJSON(data: TuningTable): Tuning {\n return Tuning.of(data);\n }\n\n /**\n * Cents of a frequency ratio, e.g. 3:2 for the just perfect fifth.\n *\n * A ratio is a relation between two frequencies rather than a place in a\n * temperament, so this is the same figure under every tuning.\n *\n * @param numerator Ratio numerator.\n * @param denominator Ratio denominator.\n * @returns The interval in cents.\n * @throws If either side is not a finite positive number.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Math.round(Tuning.ratioToCents(3, 2)); // 702\n * ```\n */\n static ratioToCents(numerator: number, denominator: number): number {\n return ratioToCents(numerator, denominator);\n }\n\n /**\n * The frequency ratio an interval in cents spans, the inverse of\n * {@link Tuning.ratioToCents}. Multiply a frequency by it to move the pitch\n * by that many cents.\n *\n * @param cents The interval in cents.\n * @returns The frequency ratio.\n * @throws If `cents` is not finite, or the ratio it spans falls outside the\n * range a number holds.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Tuning.centsToRatio(0); // 1\n * ```\n */\n static centsToRatio(cents: number): number {\n return centsToRatio(cents);\n }\n\n /**\n * Interval in cents between two frequencies.\n *\n * @param a Lower/first frequency in Hz.\n * @param b Upper/second frequency in Hz.\n * @returns Cents from `a` to `b`, negative when `b` is lower.\n * @throws If either frequency is not a finite positive number.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Math.round(Tuning.centsBetweenFreq(440, 880)); // 1200\n * ```\n */\n static centsBetweenFreq(a: number, b: number): number {\n return centsBetweenFreq(a, b);\n }\n\n /**\n * Cents by which a five-limit just interval departs from its 12-TET\n * tempering; positive means the just interval is the wider one.\n *\n * @param semitoneClass Semitone class in [0, 12].\n * @returns The deviation in cents.\n * @throws If `semitoneClass` is not an integer in [0, 12].\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Math.round(Tuning.justDeviationCents(7)); // 2\n * ```\n */\n static justDeviationCents(semitoneClass: number): number {\n return justDeviationCents(semitoneClass);\n }\n\n /** Step index whose frequency is {@link Tuning.refFreq}. */\n get refStep(): number {\n return this.#table.refStep;\n }\n\n /** Frequency in Hz of {@link Tuning.refStep}. */\n get refFreq(): number {\n return this.#table.refFreq;\n }\n\n /** Equal divisions of the octave; 12 is the standard temperament. */\n get divisions(): number {\n return this.#table.divisions;\n }\n\n /** A copy of the underlying plain tuning table. */\n get data(): TuningTable {\n return this.toJSON();\n }\n\n /**\n * Frequency in Hz of a note.\n *\n * The note's MIDI number is read as a step index, which is how the tuning\n * module numbers steps: under twelve divisions the two coincide, and under\n * any other the step index keeps counting from the same reference.\n *\n * @param note A note name, a MIDI number, plain note data, or a `Note`; it\n * must carry an octave, since a bare pitch class has no frequency.\n * @param tuning A temperament to read the note under instead of this one.\n * @returns The frequency in Hz.\n * @throws If the value is not a note, has no octave, or the frequency falls\n * outside the range a number holds.\n * @example\n * ```ts\n * import { Note } from '@libraz/libcantus';\n * import { Tuning } from '@libraz/libcantus';\n * const tuning = Tuning.twelveTet();\n * tuning.frequencyOf('A4'); // 440\n * tuning.frequencyOf(69); // 440\n * tuning.frequencyOf(Note.parse('A4')); // 440\n * ```\n */\n frequencyOf(note: NoteLike, tuning: TuningTable = this.#table): number {\n return frequencyOf(noteToMidi(toNoteData(note)), tuning);\n }\n\n /**\n * Frequency in Hz of a step index.\n *\n * The step-numbered form of {@link Tuning.frequencyOf}, for the steps of a\n * temperament that no twelve-tone note names.\n *\n * @param step Step index; a MIDI number under twelve divisions.\n * @param tuning A temperament to read the step under instead of this one.\n * @returns The frequency in Hz.\n * @throws If the step is not finite, or the frequency falls outside the range\n * a number holds.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * const et19 = Tuning.edo(19);\n * et19.frequencyOfStep(69); // 440\n * et19.frequencyOfStep(70) > 440; // true\n * ```\n */\n frequencyOfStep(step: number, tuning: TuningTable = this.#table): number {\n return frequencyOf(step, tuning);\n }\n\n /**\n * Nearest step index to a frequency, the rounded inverse of\n * {@link Tuning.frequencyOfStep}.\n *\n * @param freq Frequency in Hz.\n * @param tuning A temperament to read the frequency under instead of this one.\n * @returns The nearest step index.\n * @throws If the frequency is not a finite positive number.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Tuning.twelveTet().nearestStep(442); // 69\n * ```\n */\n nearestStep(freq: number, tuning: TuningTable = this.#table): number {\n return nearestStep(freq, tuning);\n }\n\n /**\n * Step index of a frequency, unrounded.\n *\n * The exact inverse of {@link Tuning.frequencyOfStep}, keeping how far off\n * the pitch sits — the figure a tuner display or a pitch-bend amount is built\n * on, which {@link Tuning.nearestStep} rounds away.\n *\n * @param freq Frequency in Hz.\n * @param tuning A temperament to read the frequency under instead of this one.\n * @returns The fractional step index.\n * @throws If the frequency is not a finite positive number.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Tuning.twelveTet().stepOf(442) > 69; // true\n * ```\n */\n stepOf(freq: number, tuning: TuningTable = this.#table): number {\n return stepOf(freq, tuning);\n }\n\n /**\n * How far a frequency sits from its nearest step, in cents; positive means\n * sharp of the step, negative flat.\n *\n * @param freq Frequency in Hz.\n * @param tuning A temperament to read the frequency under instead of this one.\n * @returns The signed deviation in cents.\n * @throws If the frequency is not a finite positive number.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Math.round(Tuning.twelveTet().centsFromNearestStep(442)); // 8\n * ```\n */\n centsFromNearestStep(freq: number, tuning: TuningTable = this.#table): number {\n return centsFromNearestStep(freq, tuning);\n }\n\n /**\n * Cents spanned by a number of steps.\n *\n * @param steps Number of steps.\n * @param tuning A temperament to measure the steps in instead of this one.\n * @returns The cents.\n * @throws If the step count is not finite.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Tuning.twelveTet().centsOfSteps(1); // 100\n * ```\n */\n centsOfSteps(steps: number, tuning: TuningTable = this.#table): number {\n return centsOfSteps(steps, tuning);\n }\n\n /**\n * Steps spanned by an interval in cents, unrounded — the inverse of\n * {@link Tuning.centsOfSteps}.\n *\n * @param cents The interval in cents.\n * @param tuning A temperament to measure the interval in instead of this one.\n * @returns The fractional step count.\n * @throws If the cents are not finite.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Tuning.twelveTet().stepsOfCents(700); // 7\n * ```\n */\n stepsOfCents(cents: number, tuning: TuningTable = this.#table): number {\n return stepsOfCents(cents, tuning);\n }\n\n /**\n * Whether another tuning divides the octave the same way from the same\n * reference pitch.\n *\n * @param other The tuning to compare with.\n * @returns True when reference step, reference frequency, and divisions all\n * match.\n */\n equals(other: Tuning): boolean {\n // The other tuning is read through its public accessors rather than its\n // private field: a bundler that emits two copies of this class — as a\n // CommonJS build without shared chunks does for the root and /model\n // entries — would otherwise throw on the brand check.\n return (\n this.#table.refStep === other.refStep &&\n this.#table.refFreq === other.refFreq &&\n this.#table.divisions === other.divisions\n );\n }\n\n /**\n * The plain tuning table, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(tuning)` from collapsing to `{}`.\n *\n * @returns A copy of the reference step, reference frequency, and divisions.\n */\n toJSON(): TuningTable {\n return {\n refStep: this.#table.refStep,\n refFreq: this.#table.refFreq,\n divisions: this.#table.divisions,\n };\n }\n\n /**\n * The temperament as a readable label, so a template literal or a log line\n * reads as the tuning.\n *\n * @returns The divisions and the reference pitch, e.g.\n * `'12-EDO (step 69 = 440 Hz)'`.\n * @example\n * ```ts\n * import { Tuning } from '@libraz/libcantus';\n * Tuning.twelveTet().toString(); // '12-EDO (step 69 = 440 Hz)'\n * ```\n */\n toString(): string {\n return `${this.#table.divisions}-EDO (step ${this.#table.refStep} = ${this.#table.refFreq} Hz)`;\n }\n}\n","import { InvalidInputError } from '../core/errors/index.js';\nimport type { Note as NoteData, NoteLike } from '../core/pitch/index.js';\nimport { toNoteData } from '../core/pitch/index.js';\nimport { assertInteger, assertMidiPitch } from '../core/validation/index.js';\nimport {\n type VoiceIndependenceOptions,\n type VoiceIndependenceReport,\n voiceIndependence,\n} from '../theory/counterpoint/index.js';\nimport {\n checkPartWriting,\n checkSpecies,\n type PartWritingOptions,\n type PartWritingViolation,\n type Species,\n type SpeciesOptions,\n type SpelledVoicing,\n spellVoicing,\n} from '../theory/partwriting/index.js';\nimport {\n type EvaluateSafetyOptions,\n enumerateSafePitches,\n evaluateSafety,\n type SafetyQuery,\n type SafetyResult,\n type VoiceSnapshot,\n} from '../theory/safety/index.js';\nimport { type KeyLike, type ResolvedKey, resolveKey } from '../theory/scale/index.js';\nimport { spellPitch } from '../theory/spelling/index.js';\nimport { type ChordLike, toChordData } from '../theory/symbol/index.js';\nimport {\n nextVoicing,\n SATB_RANGES,\n type StyledVoicingOptions,\n type VoiceRange,\n type VoicingOptions,\n voiceChord,\n voiceChordStyled,\n voiceLeadingCost,\n} from '../theory/voicing/index.js';\nimport { Note } from './note.js';\nimport { assertDataArray, assertKeyArgument } from './shared.js';\n\n/**\n * The plain form of a {@link Voicing}: the sounding MIDI pitches in voice\n * order, lowest voice first.\n *\n * Voice order, not sorted order. A voicing is normally ascending, and one that\n * is not is exactly what a voice crossing is — the class keeps the order it was\n * built with so the crossing survives to be reported, so a caller reading the\n * lowest sounding pitch takes the minimum rather than the first entry.\n *\n * The voicing functions all speak this array, so the class hands out exactly\n * what they take rather than a wrapper of its own.\n */\nexport type VoicingData = number[];\n\n/**\n * Options controlling {@link Voicing.independence}.\n *\n * Everything {@link voiceIndependence} accepts, plus the key its two lines are\n * spelled in.\n */\nexport type VoicingIndependenceOptions = VoiceIndependenceOptions & {\n /**\n * The key both lines are spelled in. Without it the pitches are read as MIDI\n * and spelled with sharps, the reading {@link toNoteData} takes of a bare\n * number; the spelling decides only whether two voices moving alike keep the\n * same interval and which intervals count as perfect consonances.\n */\n key?: KeyLike;\n};\n\n/**\n * The context a candidate pitch is judged in, with the voices of this voicing\n * standing as the other parts.\n *\n * The same query serves {@link Voicing.safetyOf} and\n * {@link Voicing.safePitches}: it is everything {@link SafetyQuery} carries\n * except the candidate and the other voices, which the voicing supplies, with\n * the chord and key taken in whichever form the caller holds them. It is\n * derived from the query itself, so a field the safety module adds arrives\n * here rather than being silently dropped on the way.\n */\nexport type VoicingSafetyQuery = Omit<\n SafetyQuery,\n 'candidatePitch' | 'otherVoices' | 'chord' | 'key'\n> & {\n /** The chord sounding under the candidate, or null when none is known. */\n chord: ChordLike | null;\n /** The prevailing key. */\n key: KeyLike;\n /**\n * The voicing these voices moved from, aligned voice for voice with this\n * one. It is what lets the parallel, hidden-parallel and voice-crossing\n * rules apply: without a previous pitch per voice there is no motion to read.\n */\n previous?: Voicing;\n};\n\n/**\n * Defensive copy of the pitches, each checked as a sounding pitch.\n *\n * The order is the caller's and is never sorted into place. A voicing is\n * ascending, but a voicing that is not is exactly what {@link checkPartWriting}\n * reports as voice crossing, and sorting here would silently repair the fault\n * the check exists to find.\n */\nfunction copyPitches(pitches: readonly number[]): number[] {\n assertDataArray(pitches, 'voicing pitches');\n if (pitches.length === 0) {\n throw new InvalidInputError('a voicing must contain at least one pitch');\n }\n // Every pitch is checked rather than copied blind: a voicing holding a NaN\n // leads, spells and scores as a voicing that looks real, and the failure\n // surfaces wherever the number is finally used. MIDI is the bound the safety\n // and voicing functions already hold their pitches to.\n return pitches.map((pitch, index) => assertMidiPitch(pitch, `pitches[${index}]`));\n}\n\n/**\n * Spell a line of pitches in a key.\n *\n * A bare number is spelled by the key rather than read as a sharp-spelled MIDI\n * note, so a cantus firmus given as pitches is written the way the voicing it\n * is judged against is: the rules that read letters — the augmented second, the\n * diminished fourth — cannot be applied to two lines spelled by different\n * rules.\n */\nfunction spellLine(line: readonly NoteLike[], key: ResolvedKey): NoteData[] {\n return line.map((value) =>\n typeof value === 'number' ? spellPitch(value, key.tonic, key) : toNoteData(value),\n );\n}\n\n/**\n * A line of pitches as notes: spelled by the key when one is known, and read as\n * sharp-spelled MIDI when none is — the reading {@link toNoteData} takes of a\n * bare number.\n */\nfunction lineOf(pitches: readonly number[], key: ResolvedKey | undefined): NoteData[] {\n return key === undefined ? pitches.map((pitch) => toNoteData(pitch)) : spellLine(pitches, key);\n}\n\n/**\n * The key a chord argument carries, when it was given as a `Chord` holding one.\n *\n * Read by shape rather than by type, the way every other boundary here reads a\n * key, so a `Chord` built by a second copy of the module is still understood.\n * Plain chord data carries no key and yields nothing.\n */\nfunction carriedKeyOf(chord: ChordLike): KeyLike | undefined {\n if (typeof chord !== 'object' || chord === null) {\n return undefined;\n }\n const key = (chord as { key?: unknown }).key;\n return typeof key === 'object' && key !== null ? (key as KeyLike) : undefined;\n}\n\n/**\n * The voicing options with the chord's own key filled in.\n *\n * A chord that carries a key passes it to the voicer, so the leading tone is\n * neither doubled nor left unresolved and the letters the augmented-interval\n * rule reads are known. An explicit `opts.key` wins, which is the order\n * `Chord.voice` resolves them in — the two entry points would otherwise voice\n * the same chord differently.\n */\nfunction withCarriedKey(chord: ChordLike, opts?: VoicingOptions): VoicingOptions | undefined {\n if (opts?.key !== undefined) {\n return opts;\n }\n const key = carriedKeyOf(chord);\n return key === undefined ? opts : { ...opts, key };\n}\n\n/**\n * An immutable voicing: the pitches one chord sounds at one moment, lowest\n * voice first (index 0 = the bass), the voice order {@link voiceChord} and\n * {@link SATB_RANGES} already use.\n *\n * The order given is kept rather than sorted: a voicing whose voices are out of\n * order is one whose voices cross, which is a fault {@link Voicing.checkTo}\n * reports rather than one the class quietly repairs.\n *\n * The voicing, part-writing, counterpoint and safety functions all take the\n * same array of voices; this holds it once and passes it to each of them. Two\n * of the methods read the pitches as a line rather than a chord —\n * {@link Voicing.species} and {@link Voicing.independence}, which judge a\n * written part slot by slot — and say so.\n *\n * The individual counterpoint predicates (`createsParallelPerfect`,\n * `createsVoiceCrossing`, and the rest) stay standalone functions: they judge\n * one pair of voices at one moment, which is a question about two pitches\n * rather than about a voicing. {@link Voicing.checkTo} is the bundled check.\n *\n * @category Class API\n * @example\n * ```ts\n * import { Voicing } from '@libraz/libcantus';\n * Voicing.satb('C').pitches.length; // 4\n * ```\n */\nexport class Voicing {\n readonly #pitches: readonly number[];\n\n /**\n * Wrap a set of sounding pitches.\n *\n * @param pitches MIDI pitches, lowest voice first; the array is copied,\n * never retained or mutated, and its order is kept. A doubled pitch is\n * kept too, since doubling is how a four-voice texture states a triad.\n * @throws If the array is empty, or a pitch is not an integer in 0..127.\n */\n constructor(pitches: readonly number[]) {\n this.#pitches = Object.freeze(copyPitches(pitches));\n }\n\n /**\n * Wrap a set of sounding pitches.\n *\n * @param pitches MIDI pitches, lowest voice first.\n * @returns The voicing.\n * @throws If the array is empty, or a pitch is not an integer in 0..127.\n */\n static of(pitches: readonly number[]): Voicing {\n return new Voicing(pitches);\n }\n\n /**\n * Realize a chord as an explicit tertian voicing in a chosen style — close,\n * drop-2, drop-3, shell or rootless — independent of the SATB range search\n * {@link Voicing.satb} runs.\n *\n * @param chord A chord symbol, plain chord data, or a {@link Chord}.\n * @param opts Styled voicing options; defaults to a close voicing at octave 4.\n * @returns The voicing, ascending.\n * @throws If the voicing would not fit inside MIDI 0..127 at the given\n * octave, or if the style leaves no voice sounding.\n * @example\n * ```ts\n * import { Voicing } from '@libraz/libcantus';\n * Voicing.forChord('Dm7', { style: 'drop2' }).pitches.length; // 4\n * ```\n */\n static forChord(chord: ChordLike, opts?: StyledVoicingOptions): Voicing {\n return new Voicing(voiceChordStyled(chord, opts));\n }\n\n /**\n * Realize a chord as one pitch per voice inside the voice ranges, defaulting\n * to the four {@link SATB_RANGES}.\n *\n * The bass takes the chord's slash bass when it has one, otherwise the root;\n * the result is compact, centred in its ranges, and free of voice crossing.\n *\n * A chord that carries a key passes it to the voicer, so the leading tone is\n * not doubled; an explicit `opts.key` overrides it. That is the order\n * {@link Chord.voice} resolves them in, and the two answer alike.\n *\n * @param chord A chord symbol, plain chord data, or a {@link Chord}.\n * @param opts Voicing options; defaults to four voices in {@link SATB_RANGES}.\n * @returns The voicing, ascending.\n * @throws If no voicing fits the given ranges.\n * @example\n * ```ts\n * import { Voicing } from '@libraz/libcantus';\n * Voicing.satb('Cmaj7').range.min >= 40; // true — the bass stays in its compass\n * ```\n */\n static satb(chord: ChordLike, opts?: VoicingOptions): Voicing {\n return new Voicing(voiceChord(toChordData(chord), withCarriedKey(chord, opts)));\n }\n\n /**\n * Wrap a plain pitch array, as {@link Voicing.data} hands it out.\n *\n * @param data The MIDI pitches.\n * @returns The voicing.\n * @throws If the array is empty, or a pitch is not an integer in 0..127.\n */\n static fromData(data: readonly number[]): Voicing {\n return new Voicing(data);\n }\n\n /**\n * Rebuild a voicing from its {@link Voicing.toJSON} output.\n *\n * @param data The serialized pitches.\n * @returns The voicing.\n * @throws If the array is empty, or a pitch is not an integer in 0..127.\n */\n static fromJSON(data: readonly number[]): Voicing {\n return new Voicing(data);\n }\n\n /**\n * A copy of the default four-voice SATB ranges, ascending: the compass\n * {@link Voicing.satb} voices into and {@link Voicing.checkTo} judges a\n * four-voice exercise against.\n */\n static get satbRanges(): VoiceRange[] {\n return SATB_RANGES.map((range) => ({ min: range.min, max: range.max }));\n }\n\n /** A copy of the sounding MIDI pitches, lowest voice first. */\n get pitches(): number[] {\n return [...this.#pitches];\n }\n\n /**\n * The compass the voicing occupies: its lowest and highest sounding pitch.\n *\n * Read as a {@link VoiceRange} so it can be handed straight back as a range\n * for another voice. The pitches are searched rather than read off the ends,\n * so a voicing whose voices cross still reports the compass it sounds.\n */\n get range(): VoiceRange {\n return { min: Math.min(...this.#pitches), max: Math.max(...this.#pitches) };\n }\n\n /** A copy of the underlying plain pitch array. */\n get data(): VoicingData {\n return this.toJSON();\n }\n\n /**\n * Spell the voicing as notes with letters and octaves, so the rules that read\n * letters can be applied to it.\n *\n * Each pitch is named against the key, and against the chord sounding under\n * it when one is given, so a chord tone takes the letter its interval above\n * the root implies: the third of a D major chord in C major spells F#, not\n * Gb.\n *\n * @param key A key name, a plain key/scale, or a {@link Key}.\n * @param chord The chord sounding, supplying the enharmonic evidence; without\n * it the key alone decides.\n * @returns One spelled note per pitch, in voice order.\n * @throws If the value names no key or no chord.\n * @example\n * ```ts\n * import { Voicing } from '@libraz/libcantus';\n * Voicing.of([50, 57, 66, 69]).spell('C major', 'D').map((note) => note.name);\n * // ['D3', 'A3', 'F#4', 'A4']\n * ```\n */\n spell(key: KeyLike, chord?: ChordLike): Note[] {\n assertKeyArgument(key, 'voicing key');\n return this.#spelled(resolveKey(key), chord).map((note) => new Note(note));\n }\n\n /**\n * Voice a chord to follow smoothly from this voicing.\n *\n * Candidates are enumerated within the ranges `opts` names, or — when neither\n * `voices` nor `ranges` is given — within a one-octave window around each of\n * these pitches, so the answer keeps this voicing's voice count. Each is\n * scored by structural quality, motion from here, and a large penalty per\n * counterpoint violation. A chord that carries a key passes it to the voicer\n * unless `opts.key` names another one.\n *\n * The rules read from the chord being left — a chordal seventh's resolution,\n * a leading tone's resolution, and the cross relation between the two chords\n * — are scored only when `opts.previousChord` names that chord: a voicing\n * does not say what it was written on.\n *\n * @param chord A chord symbol, plain chord data, or a {@link Chord}.\n * @param opts Voicing options; when omitted, the ranges follow this voicing.\n * @returns The chosen voicing.\n * @throws If this voicing has fewer voices than the requested ranges, or no\n * voicing fits them.\n * @example\n * ```ts\n * import { Voicing } from '@libraz/libcantus';\n * const tonic = Voicing.satb('C');\n * tonic.costTo(tonic.next('G7')) < 24; // true — the voices move economically\n * ```\n */\n next(chord: ChordLike, opts?: VoicingOptions): Voicing {\n return new Voicing(nextVoicing(this.pitches, toChordData(chord), withCarriedKey(chord, opts)));\n }\n\n /**\n * The voice-leading cost from this voicing to another: the summed absolute\n * semitone motion across voices, and nothing besides. What the motion breaks\n * is {@link Voicing.checkTo}'s question.\n *\n * @param other The voicing moved to.\n * @returns The cost, or `Infinity` when the two hold a different number of\n * voices and are therefore not comparable.\n */\n costTo(other: Voicing): number {\n return voiceLeadingCost(this.pitches, other.pitches);\n }\n\n /**\n * Check the motion from this voicing to another against the four-part rules,\n * and report every rule the pair breaks.\n *\n * Both voicings are spelled in `key` against the chord each realizes, then\n * graded as a two-chord exercise: voice crossing, spacing and range inside\n * each chord, and parallel and hidden perfects, overlap, cross relations,\n * augmented melodic intervals and unresolved tendency tones between them.\n *\n * @param other The voicing moved to.\n * @param chords The chord this voicing realizes and the chord `other` does.\n * @param key The key the exercise is written in; it names the leading tone.\n * @param opts Ranges and the upper-voice spacing limit; a four-voice pair is\n * judged against {@link SATB_RANGES} when no ranges are given.\n * @returns Every violation found, in musical order; an empty array for a\n * clean pair.\n * @throws If a value names no chord or key, or the ranges are malformed or\n * too few for the voices being checked.\n * @example\n * ```ts\n * import { Voicing } from '@libraz/libcantus';\n * const from = Voicing.of([48, 55, 64, 72]);\n * const to = Voicing.of([50, 57, 65, 69]);\n * from.checkTo(to, ['C', 'Dm'], 'C major').map((found) => found.kind);\n * // ['parallelFifth']\n * ```\n */\n checkTo(\n other: Voicing,\n chords: readonly [ChordLike, ChordLike],\n key: KeyLike,\n opts?: PartWritingOptions,\n ): PartWritingViolation[] {\n assertKeyArgument(key, 'voicing key');\n // The key is passed on whole rather than reduced to its pitch classes: the\n // exercise is graded on the letters it is written with, so an Ab minor is\n // spelled on flats here and everywhere the checker reads it.\n const resolved = resolveKey(key);\n const from = toChordData(chords[0]);\n const to = toChordData(chords[1]);\n const voicings: SpelledVoicing[] = [\n spellVoicing(this.pitches, from, resolved),\n spellVoicing(other.pitches, to, resolved),\n ];\n return checkPartWriting(voicings, [from, to], resolved, opts);\n }\n\n /**\n * Mark this voicing, read as a written counterpoint line, against a cantus\n * firmus in one of the five species.\n *\n * The pitches are the counterpoint, one per slot rather than one per voice:\n * this is the one place where the array is a line in time instead of a chord\n * in register. Both lines are spelled in `mode`, since half of what the\n * species rules forbid — the augmented second, the diminished fourth — is\n * invisible in a pitch.\n *\n * @param cantusFirmus The given voice, one note per measure, as note names,\n * plain notes, MIDI pitches, or {@link Note} instances.\n * @param species Which species the exercise is written in.\n * @param mode The mode the exercise is in.\n * @param opts Note lengths, and which side the counterpoint is written on;\n * the fifth species cannot be read without `durations`.\n * @returns Every violation found, in the order the exercise commits them.\n * @throws If the species is not one of the five, the cantus firmus is empty,\n * or the fifth species is given without durations.\n * @example\n * ```ts\n * import { Voicing } from '@libraz/libcantus';\n * const counterpoint = Voicing.of([72, 69, 67, 71, 72]);\n * counterpoint.species(['C4', 'D4', 'E4', 'D4', 'C4'], 1, 'C major').length; // 0\n * ```\n */\n species(\n cantusFirmus: readonly NoteLike[],\n species: Species,\n mode: KeyLike,\n opts?: SpeciesOptions,\n ): PartWritingViolation[] {\n assertKeyArgument(mode, 'voicing mode');\n const resolved = resolveKey(mode);\n // Both lines are spelled by the same reading, so a cantus firmus given as\n // pitches is written the way this one is: the rules that read letters\n // cannot be applied to two lines spelled by different rules.\n return checkSpecies(\n spellLine(cantusFirmus, resolved),\n spellLine(this.#pitches, resolved),\n species,\n resolved,\n opts,\n );\n }\n\n /**\n * Measure how independent this voicing, read as a line, is from another.\n *\n * As in {@link Voicing.species} the pitches are slots in time, one per entry,\n * aligned with `other` slot for slot. Nothing here is a verdict: parallel\n * thirds report as parallel motion with a small separation, a pedal point as\n * oblique motion.\n *\n * @param other The line measured against this one, of the same length.\n * @param opts Attack flags, the treatment of the fourth, and the key both\n * lines are spelled in.\n * @returns The motion breakdown, rhythmic complementarity, separation,\n * crossings, and the longest perfect-consonance run.\n * @throws If the two lines differ in length, or an attack array is supplied\n * at another length than the lines.\n */\n independence(other: Voicing, opts?: VoicingIndependenceOptions): VoiceIndependenceReport {\n // `key` is this class's own addition: it spells the two lines and has no\n // meaning below. Forwarding the bag whole would hand a `KeyLike` to a\n // delegate that today discards it and tomorrow may read a `key` of its\n // own, so it is taken out here rather than relied on being ignored.\n const { key, ...rest } = opts ?? {};\n const resolved = key === undefined ? undefined : resolveKey(key);\n return voiceIndependence(\n lineOf(this.#pitches, resolved),\n lineOf(other.pitches, resolved),\n rest,\n );\n }\n\n /**\n * Judge a candidate pitch placed against these voices.\n *\n * Every pitch of this voicing stands as another part sounding under the\n * candidate, so the vertical rules read them all; the motion rules need\n * `query.previous`, which gives each of those voices the pitch it came from.\n *\n * @param pitch The candidate MIDI pitch.\n * @param query The candidate's harmonic and voice-leading context.\n * @param opts Set `suggestions: false` to skip the search for safe\n * replacements when the verdict is not safe, and `partners: true` to learn\n * which voice of this voicing, by index, raised each pairwise flag.\n * @returns The verdict, reason bitmask, and optional resolution guidance.\n * @throws If the profile is unknown, a value names no chord or key, or a\n * pitch is not a MIDI pitch in 0..127.\n * @example\n * ```ts\n * import { NoteSafety } from '@libraz/libcantus';\n * import { Voicing } from '@libraz/libcantus';\n * const sounding = Voicing.of([48, 55, 64]);\n * sounding.safetyOf(72, { profile: 'pop', chord: 'C', key: 'C major', strongBeat: true })\n * .safety === NoteSafety.Safe; // true\n * ```\n */\n safetyOf(pitch: number, query: VoicingSafetyQuery, opts?: EvaluateSafetyOptions): SafetyResult {\n return evaluateSafety({ ...this.#context(query), candidatePitch: pitch }, opts);\n }\n\n /**\n * Enumerate the pitches placeable against these voices in a range, chord\n * tones first, each group descending.\n *\n * @param query The harmonic and voice-leading context, as\n * {@link Voicing.safetyOf} reads it.\n * @param pitchLow Lowest MIDI pitch to consider (inclusive).\n * @param pitchHigh Highest MIDI pitch to consider (inclusive).\n * @returns The placeable pitches — those not judged dissonant.\n * @throws If the profile is unknown, a value names no chord or key, or a\n * bound is not a MIDI pitch in 0..127 or is reversed.\n */\n safePitches(query: VoicingSafetyQuery, pitchLow: number, pitchHigh: number): number[] {\n return enumerateSafePitches(this.#context(query), pitchLow, pitchHigh);\n }\n\n /**\n * The n-th inversion of the voicing: the lowest voice taken up an octave, n\n * times over.\n *\n * A negative `n` takes the highest voice down an octave as many times, and\n * `invert(0)` is the voicing itself, voice order and all. Unlike\n * {@link Chord.invert}, which rotates a chord's interval template, this moves\n * real voices: inverting a four-voice texture four times leaves the same chord\n * an octave higher. A voicing that actually inverts comes back ascending,\n * since the voice that moved is no longer where it was.\n *\n * @param n How many voices to move, upward when positive.\n * @returns The inverted voicing, ascending; this voicing itself when `n` is 0.\n * @throws If `n` is not an integer in [-128, 128], or a voice would leave\n * MIDI 0..127.\n * @example\n * ```ts\n * import { Voicing } from '@libraz/libcantus';\n * Voicing.of([60, 64, 67]).invert(1).pitches; // [64, 67, 72]\n * ```\n */\n invert(n: number): Voicing {\n assertInteger(n, 'voicing inversion', -128, 128);\n // No voice moves, so nothing about the voicing changes — including the order\n // its voices were written in. Falling through would sort them, and a voicing\n // whose voices cross is a fault `checkTo` reports rather than one the class\n // quietly repairs.\n if (n === 0) {\n return this;\n }\n // Each move is made in turn rather than in one arithmetic step: the voice\n // that is lowest after a move is not always the next one up, so which voice\n // moves second depends on where the first one landed.\n const pitches = [...this.#pitches].sort((a, b) => a - b);\n for (let moved = 0; moved < Math.abs(n); moved += 1) {\n const index = n > 0 ? 0 : pitches.length - 1;\n const pitch = (pitches[index] as number) + (n > 0 ? 12 : -12);\n pitches.splice(index, 1);\n pitches.push(assertMidiPitch(pitch, 'inverted voice'));\n pitches.sort((a, b) => a - b);\n }\n return new Voicing(pitches);\n }\n\n /**\n * Whether another voicing sounds the same pitches in the same order.\n *\n * A doubling counts: two voices on the same pitch are two voices, and a\n * three-voice texture is not the four-voice one that doubles its root.\n *\n * @param other The voicing to compare.\n * @returns True when the pitches match one for one.\n */\n equals(other: Voicing): boolean {\n // The other voicing is read through its public accessor rather than its\n // private field: a bundler that emits two copies of this class — as a\n // CommonJS build without shared chunks does for the root and /model\n // entries — would otherwise throw on the brand check.\n const theirs = other.pitches;\n return (\n this.#pitches.length === theirs.length &&\n this.#pitches.every((pitch, index) => pitch === theirs[index])\n );\n }\n\n /**\n * The plain pitch array, for JSON serialization.\n *\n * Private class fields do not serialize, so an explicit `toJSON` keeps\n * `JSON.stringify(voicing)` from collapsing to `{}`.\n *\n * @returns A copy of the sounding MIDI pitches, in voice order.\n */\n toJSON(): VoicingData {\n return [...this.#pitches];\n }\n\n /**\n * The pitches separated by spaces, so a template literal or a log line reads\n * as the voicing.\n *\n * @returns The pitches in voice order, e.g. `'60 64 67'`.\n */\n toString(): string {\n return this.#pitches.join(' ');\n }\n\n /** Spell the voicing, by the key alone or against a chord as well. */\n #spelled(key: ResolvedKey, chord: ChordLike | undefined): NoteData[] {\n return chord === undefined\n ? spellLine(this.#pitches, key)\n : spellVoicing(this.pitches, toChordData(chord), key);\n }\n\n /** The safety context these voices supply, minus the candidate pitch. */\n #context(query: VoicingSafetyQuery): Omit<SafetyQuery, 'candidatePitch'> {\n const previous = query.previous?.pitches;\n const otherVoices: VoiceSnapshot[] = this.#pitches.map((pitch, index) => {\n const prevPitch = previous?.[index];\n return prevPitch === undefined ? { pitch } : { pitch, prevPitch };\n });\n return {\n profile: query.profile,\n chord: query.chord === null ? null : toChordData(query.chord),\n key: resolveKey(query.key).scale,\n otherVoices,\n strongBeat: query.strongBeat,\n prevPitch: query.prevPitch,\n vocalLow: query.vocalLow,\n vocalHigh: query.vocalHigh,\n };\n }\n}\n"],"mappings":"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","names":["track","tuplet","copyNote","sameNote"]}
|