@libraz/libcantus 1.1.0 → 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/dist/analyze/index.cjs +7 -7
- package/dist/analyze/index.d.cts +8 -8
- package/dist/analyze/index.d.ts +8 -8
- package/dist/analyze/index.js +6 -6
- package/dist/{chunk-TT6PKMPR.cjs → chunk-35NBV2FT.cjs} +16 -16
- package/dist/{chunk-TT6PKMPR.cjs.map → chunk-35NBV2FT.cjs.map} +1 -1
- package/dist/{chunk-YPB3A3EY.cjs → chunk-3R3QVKY5.cjs} +314 -285
- package/dist/chunk-3R3QVKY5.cjs.map +1 -0
- package/dist/{chunk-RVS4G4MR.cjs → chunk-76ZBTRG2.cjs} +198 -198
- package/dist/{chunk-RVS4G4MR.cjs.map → chunk-76ZBTRG2.cjs.map} +1 -1
- package/dist/{chunk-X6RJAHII.js → chunk-7KG3RTYS.js} +2 -2
- package/dist/{chunk-PQL7E5F6.js → chunk-AGOVW7U6.js} +1 -1
- package/dist/{chunk-PQL7E5F6.js.map → chunk-AGOVW7U6.js.map} +1 -1
- package/dist/{chunk-J772DL3B.cjs → chunk-CGBADIO5.cjs} +53 -53
- package/dist/{chunk-J772DL3B.cjs.map → chunk-CGBADIO5.cjs.map} +1 -1
- package/dist/{chunk-GDKE6RQW.cjs → chunk-DSMJRXCZ.cjs} +402 -401
- package/dist/chunk-DSMJRXCZ.cjs.map +1 -0
- package/dist/{chunk-DKICR7AN.js → chunk-FBH75DAY.js} +13 -12
- package/dist/{chunk-DKICR7AN.js.map → chunk-FBH75DAY.js.map} +1 -1
- package/dist/{chunk-VLE5R7PF.js → chunk-H2KJHBW4.js} +4 -4
- package/dist/{chunk-XVMJO3QF.cjs → chunk-HPVSH7SF.cjs} +237 -215
- package/dist/chunk-HPVSH7SF.cjs.map +1 -0
- package/dist/{chunk-QCXYKSZS.cjs → chunk-HWHGOVO6.cjs} +19 -19
- package/dist/{chunk-QCXYKSZS.cjs.map → chunk-HWHGOVO6.cjs.map} +1 -1
- package/dist/{chunk-HSY2VQXZ.js → chunk-HYJJ2V2I.js} +32 -10
- package/dist/chunk-HYJJ2V2I.js.map +1 -0
- package/dist/{chunk-5KW7DNCJ.cjs → chunk-J7FHVZII.cjs} +445 -445
- package/dist/{chunk-5KW7DNCJ.cjs.map → chunk-J7FHVZII.cjs.map} +1 -1
- package/dist/{chunk-AWEMD747.js → chunk-M5RYMAFI.js} +3 -3
- package/dist/{chunk-H66ARFU5.js → chunk-NB25P3EH.js} +3 -3
- package/dist/{chunk-57WB2EDF.js → chunk-NFJ4P6ZZ.js} +3 -3
- package/dist/{chunk-5JJ6EHEZ.cjs → chunk-NM7UAMC3.cjs} +62 -62
- package/dist/{chunk-5JJ6EHEZ.cjs.map → chunk-NM7UAMC3.cjs.map} +1 -1
- package/dist/{chunk-R7B5N2JK.cjs → chunk-PM4XJE2Y.cjs} +47 -47
- package/dist/{chunk-R7B5N2JK.cjs.map → chunk-PM4XJE2Y.cjs.map} +1 -1
- package/dist/{chunk-7GOKQJTQ.js → chunk-PUKJP2Z5.js} +2 -2
- package/dist/{chunk-R5VUXQMP.js → chunk-Q6LFSAKV.js} +7 -7
- package/dist/{chunk-FPBZFNCD.js → chunk-RFIBF2RR.js} +47 -18
- package/dist/{chunk-FPBZFNCD.js.map → chunk-RFIBF2RR.js.map} +1 -1
- package/dist/{chunk-XKSO2V5I.cjs → chunk-S5BKZZGM.cjs} +1 -1
- package/dist/{chunk-XKSO2V5I.cjs.map → chunk-S5BKZZGM.cjs.map} +1 -1
- package/dist/{chunk-Q6R3QAZD.cjs → chunk-SGLEQVJH.cjs} +332 -332
- package/dist/{chunk-Q6R3QAZD.cjs.map → chunk-SGLEQVJH.cjs.map} +1 -1
- package/dist/{chunk-HOHFYGKW.js → chunk-UMWZ4ZET.js} +2 -2
- package/dist/{coerce-wwdELNYS.d.ts → coerce-DP0vYu-x.d.ts} +77 -1
- package/dist/{coerce-CJlgULrQ.d.cts → coerce-DRERzdve.d.cts} +77 -1
- package/dist/core/index.cjs +5 -5
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +4 -4
- package/dist/generate/index.cjs +8 -8
- package/dist/generate/index.d.cts +8 -8
- package/dist/generate/index.d.ts +8 -8
- package/dist/generate/index.js +7 -7
- package/dist/{index-BaoKVVhE.d.cts → index-B9QLziDe.d.cts} +2 -2
- package/dist/{index-B3WCj_Hm.d.cts → index-BBWNZS0f.d.cts} +2 -2
- package/dist/{index-CnHQgqNh.d.ts → index-BHIUyjhZ.d.ts} +2 -2
- package/dist/{index-DpC-mDlV.d.ts → index-BJgP97N1.d.ts} +4 -4
- package/dist/{index-CBCP84rv.d.cts → index-BL5N2Oyz.d.cts} +1 -1
- package/dist/{index-D_hzxD8w.d.cts → index-BMweUlm5.d.cts} +3 -0
- package/dist/{index-BzLNkmA7.d.cts → index-BNSM-DSk.d.cts} +4 -4
- package/dist/{index-BUtIf2go.d.ts → index-BRMbPkHE.d.ts} +25 -5
- package/dist/{index-BpWOhkkE.d.ts → index-CJBBiAmU.d.ts} +2 -2
- package/dist/{index-Ci3xyows.d.ts → index-CL4b4gUQ.d.ts} +3 -0
- package/dist/{index-DTsKaPaC.d.cts → index-DGCNKAUr.d.cts} +25 -5
- package/dist/{index-CnIdP4EZ.d.ts → index-Dw2DP7vm.d.ts} +1 -1
- package/dist/index.cjs +13 -13
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +12 -12
- package/dist/{masks-O73Rhj5d.d.ts → masks-Cc7-MzzY.d.ts} +1 -1
- package/dist/{masks-C8TWLFIi.d.cts → masks-pADfTOiD.d.cts} +1 -1
- package/dist/model/index.cjs +12 -12
- package/dist/model/index.d.cts +16 -15
- package/dist/model/index.d.ts +16 -15
- package/dist/model/index.js +11 -11
- package/dist/theory/index.cjs +5 -5
- package/dist/theory/index.d.cts +7 -7
- package/dist/theory/index.d.ts +7 -7
- package/dist/theory/index.js +4 -4
- package/package.json +6 -5
- package/dist/chunk-GDKE6RQW.cjs.map +0 -1
- package/dist/chunk-HSY2VQXZ.js.map +0 -1
- package/dist/chunk-XVMJO3QF.cjs.map +0 -1
- package/dist/chunk-YPB3A3EY.cjs.map +0 -1
- /package/dist/{chunk-X6RJAHII.js.map → chunk-7KG3RTYS.js.map} +0 -0
- /package/dist/{chunk-VLE5R7PF.js.map → chunk-H2KJHBW4.js.map} +0 -0
- /package/dist/{chunk-AWEMD747.js.map → chunk-M5RYMAFI.js.map} +0 -0
- /package/dist/{chunk-H66ARFU5.js.map → chunk-NB25P3EH.js.map} +0 -0
- /package/dist/{chunk-57WB2EDF.js.map → chunk-NFJ4P6ZZ.js.map} +0 -0
- /package/dist/{chunk-7GOKQJTQ.js.map → chunk-PUKJP2Z5.js.map} +0 -0
- /package/dist/{chunk-R5VUXQMP.js.map → chunk-Q6LFSAKV.js.map} +0 -0
- /package/dist/{chunk-HOHFYGKW.js.map → chunk-UMWZ4ZET.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunk35NBV2FTcjs = require('./chunk-35NBV2FT.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
@@ -47,7 +47,7 @@ var _chunkTT6PKMPRcjs = require('./chunk-TT6PKMPR.cjs');
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
var
|
|
50
|
+
var _chunk3R3QVKY5cjs = require('./chunk-3R3QVKY5.cjs');
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
|
|
@@ -77,18 +77,18 @@ var _chunkYPB3A3EYcjs = require('./chunk-YPB3A3EY.cjs');
|
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
|
|
80
|
-
var
|
|
80
|
+
var _chunkS5BKZZGMcjs = require('./chunk-S5BKZZGM.cjs');
|
|
81
81
|
|
|
82
82
|
// src/analyze/detect/modes.ts
|
|
83
83
|
var MODAL_CANDIDATES = Object.freeze([
|
|
84
|
-
{ scaleName: "dorian", mode: "minor", mask:
|
|
85
|
-
{ scaleName: "phrygian", mode: "minor", mask:
|
|
86
|
-
{ scaleName: "lydian", mode: "major", mask:
|
|
87
|
-
{ scaleName: "mixolydian", mode: "major", mask:
|
|
84
|
+
{ scaleName: "dorian", mode: "minor", mask: _chunk3R3QVKY5cjs.DORIAN_MASK, substitutions: [[8, 9]] },
|
|
85
|
+
{ scaleName: "phrygian", mode: "minor", mask: _chunk3R3QVKY5cjs.PHRYGIAN_MASK, substitutions: [[2, 1]] },
|
|
86
|
+
{ scaleName: "lydian", mode: "major", mask: _chunk3R3QVKY5cjs.LYDIAN_MASK, substitutions: [[5, 6]] },
|
|
87
|
+
{ scaleName: "mixolydian", mode: "major", mask: _chunk3R3QVKY5cjs.MIXOLYDIAN_MASK, substitutions: [[11, 10]] },
|
|
88
88
|
{
|
|
89
89
|
scaleName: "locrian",
|
|
90
90
|
mode: "minor",
|
|
91
|
-
mask:
|
|
91
|
+
mask: _chunk3R3QVKY5cjs.LOCRIAN_MASK,
|
|
92
92
|
substitutions: [
|
|
93
93
|
[2, 1],
|
|
94
94
|
[7, 6]
|
|
@@ -115,12 +115,12 @@ function resolveModalCandidates(modes) {
|
|
|
115
115
|
return MODAL_CANDIDATES;
|
|
116
116
|
}
|
|
117
117
|
if (!Array.isArray(modes)) {
|
|
118
|
-
throw new (0,
|
|
118
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)("modes must be a boolean or an array of mode names");
|
|
119
119
|
}
|
|
120
120
|
const requested = new Set(modes);
|
|
121
121
|
for (const name of requested) {
|
|
122
122
|
if (!MODAL_SCALE_NAMES.some((known) => known === name)) {
|
|
123
|
-
throw new (0,
|
|
123
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(
|
|
124
124
|
`unknown mode '${String(name)}'; expected one of ${MODAL_SCALE_NAMES.join(", ")}`
|
|
125
125
|
);
|
|
126
126
|
}
|
|
@@ -131,7 +131,7 @@ function resolveModalCandidates(modes) {
|
|
|
131
131
|
// src/analyze/adjacency.ts
|
|
132
132
|
var HUMANIZE_ADJACENCY = 0.05;
|
|
133
133
|
function sameInstant(beat, other) {
|
|
134
|
-
return Math.abs(beat - other) <=
|
|
134
|
+
return Math.abs(beat - other) <= _chunkS5BKZZGMcjs.BEAT_EPS;
|
|
135
135
|
}
|
|
136
136
|
function adjacent(prevEnd, nextStart) {
|
|
137
137
|
return Math.abs(nextStart - prevEnd) <= HUMANIZE_ADJACENCY;
|
|
@@ -145,7 +145,7 @@ var MAX_VELOCITY = 127;
|
|
|
145
145
|
var ACCENT_DIVISOR = 3;
|
|
146
146
|
function noteWeight(note, beats, meter) {
|
|
147
147
|
const velocityFactor = note.velocity !== void 0 ? note.velocity / MAX_VELOCITY : 1;
|
|
148
|
-
const accent = meter === void 0 ? 1 : 1 +
|
|
148
|
+
const accent = meter === void 0 ? 1 : 1 + _chunkS5BKZZGMcjs.metricWeight.call(void 0, note.startBeat, meter) / ACCENT_DIVISOR;
|
|
149
149
|
return beats * velocityFactor * accent;
|
|
150
150
|
}
|
|
151
151
|
function bucketNotesBySlot(notes, grid, slotCount, opts) {
|
|
@@ -158,7 +158,7 @@ function bucketNotesBySlot(notes, grid, slotCount, opts) {
|
|
|
158
158
|
Math.ceil((note.startBeat + note.durationBeat - grid.origin) / grid.slotBeats)
|
|
159
159
|
);
|
|
160
160
|
memberships += Math.max(0, lastExclusive - first);
|
|
161
|
-
|
|
161
|
+
_chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, memberships, opts.name, opts.budget);
|
|
162
162
|
for (let slot = first; slot < lastExclusive; slot += 1) {
|
|
163
163
|
_optionalChain([buckets, 'access', _2 => _2[slot], 'optionalAccess', _3 => _3.push, 'call', _4 => _4(note)]);
|
|
164
164
|
}
|
|
@@ -171,14 +171,14 @@ function windowWeights(notes, windowStart, windowEnd, meter) {
|
|
|
171
171
|
for (const note of notes) {
|
|
172
172
|
const noteEnd = note.startBeat + note.durationBeat;
|
|
173
173
|
const overlap = Math.min(noteEnd, windowEnd) - Math.max(note.startBeat, windowStart);
|
|
174
|
-
if (overlap <=
|
|
174
|
+
if (overlap <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
175
175
|
continue;
|
|
176
176
|
}
|
|
177
|
-
const onsetInWindow = note.startBeat >= windowStart -
|
|
178
|
-
const pc =
|
|
177
|
+
const onsetInWindow = note.startBeat >= windowStart - _chunkS5BKZZGMcjs.BEAT_EPS && note.startBeat < windowEnd - _chunkS5BKZZGMcjs.BEAT_EPS;
|
|
178
|
+
const pc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, note.pitch);
|
|
179
179
|
const weight = noteWeight(note, overlap, onsetInWindow ? meter : void 0);
|
|
180
180
|
weights[pc] = (_nullishCoalesce(weights[pc], () => ( 0))) + weight;
|
|
181
|
-
if (weight >
|
|
181
|
+
if (weight > _chunkS5BKZZGMcjs.BEAT_EPS && note.pitch < lowestPitch) {
|
|
182
182
|
lowestPitch = note.pitch;
|
|
183
183
|
}
|
|
184
184
|
}
|
|
@@ -213,12 +213,12 @@ var NAMED_PROFILES = {
|
|
|
213
213
|
};
|
|
214
214
|
function assertProfileVector(vector, name) {
|
|
215
215
|
if (vector.length !== PROFILE_LENGTH) {
|
|
216
|
-
throw new (0,
|
|
216
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`${name} must have ${PROFILE_LENGTH} entries`);
|
|
217
217
|
}
|
|
218
218
|
for (let index = 0; index < vector.length; index += 1) {
|
|
219
219
|
const value = vector[index];
|
|
220
220
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
221
|
-
throw new (0,
|
|
221
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`${name}[${index}] must be a finite number`);
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
224
|
}
|
|
@@ -229,18 +229,18 @@ function resolveKeyProfile(profile) {
|
|
|
229
229
|
if (typeof profile === "string") {
|
|
230
230
|
const named = NAMED_PROFILES[profile];
|
|
231
231
|
if (named === void 0) {
|
|
232
|
-
throw new (0,
|
|
232
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(
|
|
233
233
|
`unknown key profile '${profile}'; expected one of ${Object.keys(NAMED_PROFILES).join(", ")}`
|
|
234
234
|
);
|
|
235
235
|
}
|
|
236
236
|
return named;
|
|
237
237
|
}
|
|
238
238
|
if (typeof profile !== "object" || profile === null) {
|
|
239
|
-
throw new (0,
|
|
239
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)("profile must be a profile name or a { major, minor } pair");
|
|
240
240
|
}
|
|
241
241
|
const { major, minor } = profile;
|
|
242
242
|
if (!Array.isArray(major) || !Array.isArray(minor)) {
|
|
243
|
-
throw new (0,
|
|
243
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)("profile must carry a major and a minor vector");
|
|
244
244
|
}
|
|
245
245
|
assertProfileVector(major, "profile.major");
|
|
246
246
|
assertProfileVector(minor, "profile.minor");
|
|
@@ -290,44 +290,44 @@ function profileScore(dist, vector, tonic) {
|
|
|
290
290
|
|
|
291
291
|
// src/analyze/detect/index.ts
|
|
292
292
|
function uniquePitchClasses(pitches) {
|
|
293
|
-
return [...new Set(pitches.map(
|
|
293
|
+
return [...new Set(pitches.map(_chunkS5BKZZGMcjs.pitchClassOf))].sort((a, b) => a - b);
|
|
294
294
|
}
|
|
295
295
|
function assertPitches(pitches, name, budget = void 0) {
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
_chunkS5BKZZGMcjs.assertArray.call(void 0, pitches, name);
|
|
297
|
+
_chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, pitches.length, name, budget);
|
|
298
298
|
for (let index = 0; index < pitches.length; index += 1) {
|
|
299
|
-
|
|
299
|
+
_chunkS5BKZZGMcjs.assertMidiPitch.call(void 0, _nullishCoalesce(pitches[index], () => ( Number.NaN)), `pitches[${index}]`);
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
function detectChord(pitches, opts = {}) {
|
|
303
|
-
const asked =
|
|
303
|
+
const asked = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
|
|
304
304
|
assertPitches(pitches, "chord detection pitches");
|
|
305
|
-
if (asked.bassPc !== void 0)
|
|
305
|
+
if (asked.bassPc !== void 0) _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, asked.bassPc, "bassPc");
|
|
306
306
|
const input = uniquePitchClasses(pitches);
|
|
307
307
|
if (input.length === 0) {
|
|
308
308
|
return [];
|
|
309
309
|
}
|
|
310
310
|
const inputKind = asked.input === void 0 || asked.input === "auto" ? pitches.every((pitch) => Number.isInteger(pitch) && pitch >= 0 && pitch <= 11) ? "pitchClass" : "midi" : asked.input;
|
|
311
|
-
const bassPc = asked.bassPc !== void 0 ?
|
|
311
|
+
const bassPc = asked.bassPc !== void 0 ? _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, asked.bassPc) : inputKind === "midi" ? _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, pitches.reduce((lowest, pitch) => Math.min(lowest, pitch), Infinity)) : void 0;
|
|
312
312
|
const inputSet = new Set(input);
|
|
313
313
|
const matches = [];
|
|
314
|
-
const qualities =
|
|
314
|
+
const qualities = _chunk3R3QVKY5cjs.chordQualities.call(void 0, );
|
|
315
315
|
const toneCounts = new Map(
|
|
316
|
-
qualities.map((quality) => [quality,
|
|
316
|
+
qualities.map((quality) => [quality, _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, _chunk3R3QVKY5cjs.makeChord.call(void 0, 0, quality)).length])
|
|
317
317
|
);
|
|
318
318
|
const qualityRank = new Map(qualities.map((quality, index) => [quality, index]));
|
|
319
319
|
for (const rootPc of input) {
|
|
320
320
|
for (const quality of qualities) {
|
|
321
|
-
const chord =
|
|
322
|
-
const tones =
|
|
321
|
+
const chord = _chunk3R3QVKY5cjs.makeChord.call(void 0, rootPc, quality);
|
|
322
|
+
const tones = _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord);
|
|
323
323
|
const toneSet = new Set(tones);
|
|
324
324
|
const missingPcs = tones.filter((pc) => !inputSet.has(pc));
|
|
325
|
-
const fifthPc =
|
|
325
|
+
const fifthPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc + 7);
|
|
326
326
|
if (missingPcs.length > 1 || missingPcs.length === 1 && missingPcs[0] !== fifthPc) {
|
|
327
327
|
continue;
|
|
328
328
|
}
|
|
329
329
|
const extraPcs = input.filter((pc) => !toneSet.has(pc));
|
|
330
|
-
const bassIndex = bassPc === void 0 ? -1 : chord.intervals.findIndex((iv) =>
|
|
330
|
+
const bassIndex = bassPc === void 0 ? -1 : chord.intervals.findIndex((iv) => _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc + iv) === bassPc);
|
|
331
331
|
const inversion = bassPc === void 0 || bassIndex < 0 ? null : bassIndex;
|
|
332
332
|
const match = {
|
|
333
333
|
rootPc,
|
|
@@ -372,15 +372,15 @@ function detectChordBest(pitches, opts = {}) {
|
|
|
372
372
|
if (!best) {
|
|
373
373
|
return null;
|
|
374
374
|
}
|
|
375
|
-
return
|
|
375
|
+
return _chunk3R3QVKY5cjs.makeChord.call(void 0, best.rootPc, best.quality, best.bassPc);
|
|
376
376
|
}
|
|
377
377
|
var MINOR_VARIANTS = [
|
|
378
|
-
{ variant: "natural", mask:
|
|
379
|
-
{ variant: "harmonic", mask:
|
|
380
|
-
{ variant: "melodic", mask:
|
|
378
|
+
{ variant: "natural", mask: _chunk3R3QVKY5cjs.NATURAL_MINOR_MASK, scaleName: "naturalMinor" },
|
|
379
|
+
{ variant: "harmonic", mask: _chunk3R3QVKY5cjs.HARMONIC_MINOR_MASK, scaleName: "harmonicMinor" },
|
|
380
|
+
{ variant: "melodic", mask: _chunk3R3QVKY5cjs.MELODIC_MINOR_MASK, scaleName: "melodicMinor" }
|
|
381
381
|
];
|
|
382
382
|
var MAJOR_VARIANTS = [
|
|
383
|
-
{ variant: "major", mask:
|
|
383
|
+
{ variant: "major", mask: _chunk3R3QVKY5cjs.MAJOR_MASK, scaleName: "major" }
|
|
384
384
|
];
|
|
385
385
|
var SCALE_NAME_ORDER = [
|
|
386
386
|
"major",
|
|
@@ -407,7 +407,7 @@ function quoteScores(rival, winner) {
|
|
|
407
407
|
return `${rival.toFixed(digits)} against ${winner.toFixed(digits)}`;
|
|
408
408
|
}
|
|
409
409
|
function keyLabel(match) {
|
|
410
|
-
const tonic =
|
|
410
|
+
const tonic = _chunkS5BKZZGMcjs.formatNote.call(void 0, _chunk3R3QVKY5cjs.spelledKeyOf.call(void 0, match.key).tonic);
|
|
411
411
|
const scale = match.scaleName.replace(/([A-Z])/g, " $1").toLowerCase();
|
|
412
412
|
return `${tonic} ${scale}`;
|
|
413
413
|
}
|
|
@@ -438,11 +438,11 @@ function explainMatches(results, inputSize) {
|
|
|
438
438
|
winner.alternatives = results.slice(1, EXPLAINED_RIVALS + 1).map((rival) => ({ label: keyLabel(rival), reason: keyRivalReason(winner, rival) }));
|
|
439
439
|
}
|
|
440
440
|
function detectKey(pitches, opts = {}) {
|
|
441
|
-
const asked =
|
|
441
|
+
const asked = _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "opts");
|
|
442
442
|
assertPitches(pitches, "key detection pitches", asked.budget);
|
|
443
443
|
const weights = asked.weights;
|
|
444
444
|
if (weights !== void 0 && weights.length !== pitches.length) {
|
|
445
|
-
throw new (0,
|
|
445
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)("weights must have one entry per pitch");
|
|
446
446
|
}
|
|
447
447
|
const profile = resolveKeyProfile(opts.profile);
|
|
448
448
|
const modalCandidates = resolveModalCandidates(opts.modes).map((candidate) => ({
|
|
@@ -453,11 +453,11 @@ function detectKey(pitches, opts = {}) {
|
|
|
453
453
|
let total = 0;
|
|
454
454
|
for (let index = 0; index < pitches.length; index += 1) {
|
|
455
455
|
const weight = weights === void 0 ? 1 : _nullishCoalesce(weights[index], () => ( 0));
|
|
456
|
-
|
|
456
|
+
_chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, weight, `weights[${index}]`);
|
|
457
457
|
if (weight <= 0) {
|
|
458
458
|
continue;
|
|
459
459
|
}
|
|
460
|
-
const pc =
|
|
460
|
+
const pc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, _nullishCoalesce(pitches[index], () => ( 0)));
|
|
461
461
|
counts.set(pc, (_nullishCoalesce(counts.get(pc), () => ( 0))) + weight);
|
|
462
462
|
total += weight;
|
|
463
463
|
}
|
|
@@ -538,8 +538,8 @@ function detectKey(pitches, opts = {}) {
|
|
|
538
538
|
return results;
|
|
539
539
|
}
|
|
540
540
|
function detectKeyFromNotes(notes, opts = {}) {
|
|
541
|
-
const asked =
|
|
542
|
-
|
|
541
|
+
const asked = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
|
|
542
|
+
_chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, notes, "key detection notes", {
|
|
543
543
|
allowNonPositiveDuration: true,
|
|
544
544
|
budget: asked.budget
|
|
545
545
|
});
|
|
@@ -561,40 +561,40 @@ function detectKeyBest(pitches, opts = {}) {
|
|
|
561
561
|
|
|
562
562
|
// src/analyze/functional/internal.ts
|
|
563
563
|
function isMinorScale(key) {
|
|
564
|
-
return
|
|
564
|
+
return _chunk3R3QVKY5cjs.isMinorMask.call(void 0, key.modeMask12);
|
|
565
565
|
}
|
|
566
566
|
function parallelScale(key) {
|
|
567
567
|
return {
|
|
568
|
-
rootPc:
|
|
569
|
-
modeMask12: isMinorScale(key) ?
|
|
568
|
+
rootPc: _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc),
|
|
569
|
+
modeMask12: isMinorScale(key) ? _chunk3R3QVKY5cjs.MAJOR_MASK : _chunk3R3QVKY5cjs.NATURAL_MINOR_MASK
|
|
570
570
|
};
|
|
571
571
|
}
|
|
572
572
|
function degreeRootPc(degreeNumber, key) {
|
|
573
|
-
const tones =
|
|
573
|
+
const tones = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, key);
|
|
574
574
|
if (tones.length === 0) {
|
|
575
|
-
return
|
|
575
|
+
return _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
576
576
|
}
|
|
577
577
|
const index = ((degreeNumber - 1) % tones.length + tones.length) % tones.length;
|
|
578
|
-
return _nullishCoalesce(tones[index], () => (
|
|
578
|
+
return _nullishCoalesce(tones[index], () => ( _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc)));
|
|
579
579
|
}
|
|
580
580
|
function loweredDegrees(key) {
|
|
581
|
-
const tones =
|
|
581
|
+
const tones = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, key);
|
|
582
582
|
const out = /* @__PURE__ */ new Set();
|
|
583
583
|
if (tones.length !== 7) {
|
|
584
584
|
return out;
|
|
585
585
|
}
|
|
586
|
-
const major =
|
|
586
|
+
const major = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, { rootPc: _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunk3R3QVKY5cjs.MAJOR_MASK });
|
|
587
587
|
for (let index = 0; index < 7; index += 1) {
|
|
588
588
|
const tone = tones[index];
|
|
589
589
|
const majorTone = major[index];
|
|
590
|
-
if (tone !== void 0 && majorTone !== void 0 &&
|
|
590
|
+
if (tone !== void 0 && majorTone !== void 0 && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, majorTone - tone) === 1) {
|
|
591
591
|
out.add(index + 1);
|
|
592
592
|
}
|
|
593
593
|
}
|
|
594
594
|
return out;
|
|
595
595
|
}
|
|
596
596
|
function romanReference(key) {
|
|
597
|
-
return
|
|
597
|
+
return _chunk3R3QVKY5cjs.heptatonicFrameOf.call(void 0, key);
|
|
598
598
|
}
|
|
599
599
|
|
|
600
600
|
// src/analyze/functional/augmented-sixth.ts
|
|
@@ -606,11 +606,11 @@ var TONES_ABOVE_BASS = {
|
|
|
606
606
|
german: [0, 4, 7, 10]
|
|
607
607
|
};
|
|
608
608
|
var SPELLED_ABOVE_BASS = {
|
|
609
|
-
italian: ["P1", "M3", "A6"].map((name) =>
|
|
610
|
-
french: ["P1", "M3", "A4", "A6"].map((name) =>
|
|
611
|
-
german: ["P1", "M3", "P5", "A6"].map((name) =>
|
|
609
|
+
italian: ["P1", "M3", "A6"].map((name) => _chunkS5BKZZGMcjs.parseInterval.call(void 0, name)),
|
|
610
|
+
french: ["P1", "M3", "A4", "A6"].map((name) => _chunkS5BKZZGMcjs.parseInterval.call(void 0, name)),
|
|
611
|
+
german: ["P1", "M3", "P5", "A6"].map((name) => _chunkS5BKZZGMcjs.parseInterval.call(void 0, name))
|
|
612
612
|
};
|
|
613
|
-
var BASS_INTERVAL =
|
|
613
|
+
var BASS_INTERVAL = _chunkS5BKZZGMcjs.parseInterval.call(void 0, "m6");
|
|
614
614
|
var CHORD_SHAPE = {
|
|
615
615
|
italian: { rootAboveBass: 0, quality: "dom7", intervals: [0, 4, 10] },
|
|
616
616
|
french: { rootAboveBass: 6, quality: "7b5", intervals: [0, 4, 6, 10] },
|
|
@@ -629,7 +629,7 @@ var SYMBOL_BY_KIND = {
|
|
|
629
629
|
german: "Ger6"
|
|
630
630
|
};
|
|
631
631
|
function bassPcOf(key) {
|
|
632
|
-
return
|
|
632
|
+
return _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc + BASS_ABOVE_TONIC);
|
|
633
633
|
}
|
|
634
634
|
function bareSpelling(note) {
|
|
635
635
|
return { letter: note.letter, alter: note.alter };
|
|
@@ -643,13 +643,13 @@ function augmentedSixthChord(kind, key) {
|
|
|
643
643
|
return augmentedSixthOn(kind, key);
|
|
644
644
|
}
|
|
645
645
|
function augmentedSixthOn(kind, keyLike) {
|
|
646
|
-
const checked =
|
|
646
|
+
const checked = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, kind, KINDS, "augmented sixth kind");
|
|
647
647
|
const shape = CHORD_SHAPE[checked];
|
|
648
|
-
const { scale: key, tonic } =
|
|
648
|
+
const { scale: key, tonic } = _chunk3R3QVKY5cjs.resolveKey.call(void 0, keyLike);
|
|
649
649
|
const bassPc = bassPcOf(key);
|
|
650
|
-
const chord =
|
|
650
|
+
const chord = _chunk3R3QVKY5cjs.makeChord.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, bassPc + shape.rootAboveBass), shape.quality, bassPc);
|
|
651
651
|
chord.intervals = [...shape.intervals];
|
|
652
|
-
const bass =
|
|
652
|
+
const bass = _chunkS5BKZZGMcjs.transposeByInterval.call(void 0, tonic, BASS_INTERVAL);
|
|
653
653
|
const tones = spelledInChordOrder(checked, tonic);
|
|
654
654
|
const [root = bass] = tones;
|
|
655
655
|
chord.rootSpelling = bareSpelling(root);
|
|
@@ -660,55 +660,55 @@ function augmentedSixthOn(kind, keyLike) {
|
|
|
660
660
|
function kindOfPitchClasses(pcs, bass) {
|
|
661
661
|
for (const kind of KINDS) {
|
|
662
662
|
const tones = TONES_ABOVE_BASS[kind];
|
|
663
|
-
if (pcs.size === tones.length && tones.every((tone) => pcs.has(
|
|
663
|
+
if (pcs.size === tones.length && tones.every((tone) => pcs.has(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, bass + tone)))) {
|
|
664
664
|
return kind;
|
|
665
665
|
}
|
|
666
666
|
}
|
|
667
667
|
return null;
|
|
668
668
|
}
|
|
669
669
|
function spellingId(note) {
|
|
670
|
-
return `${
|
|
670
|
+
return `${_chunkS5BKZZGMcjs.diatonicLetterOf.call(void 0, note.letter)}:${note.alter}`;
|
|
671
671
|
}
|
|
672
672
|
function spellsAugmentedSixth(chord, kind, key) {
|
|
673
673
|
const tonic = key.tonic;
|
|
674
|
-
const written = new Set(
|
|
674
|
+
const written = new Set(_chunk3R3QVKY5cjs.spellChord.call(void 0, chord, tonic, key.scale).map(spellingId));
|
|
675
675
|
const tones = spelledFromTonic(kind, tonic).map(spellingId);
|
|
676
676
|
return written.size === tones.length && tones.every((tone) => written.has(tone));
|
|
677
677
|
}
|
|
678
678
|
function augmentedSixthKind(chord, key) {
|
|
679
|
-
return augmentedSixthKindOf(
|
|
679
|
+
return augmentedSixthKindOf(_chunk3R3QVKY5cjs.toChordData.call(void 0, chord), key);
|
|
680
680
|
}
|
|
681
681
|
function augmentedSixthKindOf(chord, keyLike) {
|
|
682
|
-
const resolved =
|
|
682
|
+
const resolved = _chunk3R3QVKY5cjs.resolveKey.call(void 0, keyLike);
|
|
683
683
|
const bass = bassPcOf(resolved.scale);
|
|
684
|
-
if (
|
|
684
|
+
if (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, _nullishCoalesce(chord.bassPc, () => ( chord.rootPc))) !== bass) {
|
|
685
685
|
return null;
|
|
686
686
|
}
|
|
687
|
-
const kind = kindOfPitchClasses(new Set(
|
|
687
|
+
const kind = kindOfPitchClasses(new Set(_chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord)), bass);
|
|
688
688
|
if (kind === null || !spellsAugmentedSixth(chord, kind, resolved)) {
|
|
689
689
|
return null;
|
|
690
690
|
}
|
|
691
691
|
return kind;
|
|
692
692
|
}
|
|
693
693
|
function augmentedSixthFromPitchClasses(pcs, bassPc, key) {
|
|
694
|
-
return augmentedSixthOverBass(
|
|
694
|
+
return augmentedSixthOverBass(_chunkS5BKZZGMcjs.assertArray.call(void 0, pcs, "pcs"), bassPc, key);
|
|
695
695
|
}
|
|
696
696
|
function augmentedSixthOverBass(pcs, bassPc, keyLike) {
|
|
697
|
-
const resolved =
|
|
697
|
+
const resolved = _chunk3R3QVKY5cjs.resolveKey.call(void 0, keyLike);
|
|
698
698
|
const bass = bassPcOf(resolved.scale);
|
|
699
|
-
if (
|
|
699
|
+
if (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, bassPc) !== bass) {
|
|
700
700
|
return null;
|
|
701
701
|
}
|
|
702
|
-
const kind = kindOfPitchClasses(new Set(pcs.map(
|
|
702
|
+
const kind = kindOfPitchClasses(new Set(pcs.map(_chunkS5BKZZGMcjs.pitchClassOf)), bass);
|
|
703
703
|
return kind === null ? null : augmentedSixthOn(kind, resolved);
|
|
704
704
|
}
|
|
705
705
|
function spellAugmentedSixth(kind, tonic) {
|
|
706
|
-
return spelledFromTonic(kind,
|
|
706
|
+
return spelledFromTonic(kind, _chunkS5BKZZGMcjs.toNoteData.call(void 0, tonic));
|
|
707
707
|
}
|
|
708
708
|
function spelledFromTonic(kind, tonic) {
|
|
709
|
-
const checked =
|
|
710
|
-
const bass =
|
|
711
|
-
return SPELLED_ABOVE_BASS[checked].map((interval) =>
|
|
709
|
+
const checked = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, kind, KINDS, "augmented sixth kind");
|
|
710
|
+
const bass = _chunkS5BKZZGMcjs.transposeByInterval.call(void 0, tonic, BASS_INTERVAL);
|
|
711
|
+
return SPELLED_ABOVE_BASS[checked].map((interval) => _chunkS5BKZZGMcjs.transposeByInterval.call(void 0, bass, interval));
|
|
712
712
|
}
|
|
713
713
|
function augmentedSixthFromSymbol(symbol, key) {
|
|
714
714
|
const kind = KIND_BY_SYMBOL.get(symbol);
|
|
@@ -724,11 +724,11 @@ var SUBDOMINANT_DEGREE = 4;
|
|
|
724
724
|
var DOMINANT_DEGREE = 5;
|
|
725
725
|
var SUBMEDIANT_DEGREE = 6;
|
|
726
726
|
function degreeOffset(degreeNumber, key) {
|
|
727
|
-
return
|
|
727
|
+
return _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, degreeRootPc(degreeNumber, romanReference(key)) - key.rootPc);
|
|
728
728
|
}
|
|
729
729
|
function thirdBelongsToKey(chord, key) {
|
|
730
730
|
return chord.intervals.some(
|
|
731
|
-
(interval) => (
|
|
731
|
+
(interval) => (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, interval) === 3 || _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, interval) === 4) && _chunk3R3QVKY5cjs.isScaleTone.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc + interval), key)
|
|
732
732
|
);
|
|
733
733
|
}
|
|
734
734
|
function deceptiveTargets(key) {
|
|
@@ -740,25 +740,25 @@ function deceptiveTargets(key) {
|
|
|
740
740
|
return borrowed === submediant ? [submediant] : [submediant, borrowed];
|
|
741
741
|
}
|
|
742
742
|
function restsOnDominant(to, key) {
|
|
743
|
-
if (
|
|
743
|
+
if (_chunk3R3QVKY5cjs.hasMajorThird.call(void 0, to) || _chunk3R3QVKY5cjs.isDominantChordOf.call(void 0, to, key)) {
|
|
744
744
|
return true;
|
|
745
745
|
}
|
|
746
|
-
if (
|
|
746
|
+
if (_chunk3R3QVKY5cjs.scaleSystemOf.call(void 0, key) !== "modal") {
|
|
747
747
|
return false;
|
|
748
748
|
}
|
|
749
|
-
const dominantPc =
|
|
750
|
-
const leadingToneDominant =
|
|
749
|
+
const dominantPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc + degreeOffset(DOMINANT_DEGREE, key));
|
|
750
|
+
const leadingToneDominant = _chunk3R3QVKY5cjs.isScaleTone.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, dominantPc + 4), key);
|
|
751
751
|
return !leadingToneDominant && thirdBelongsToKey(to, key);
|
|
752
752
|
}
|
|
753
753
|
function isTonicSixFour(chord, key) {
|
|
754
|
-
if (
|
|
754
|
+
if (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc) !== 0 || chord.bassPc === void 0) {
|
|
755
755
|
return false;
|
|
756
756
|
}
|
|
757
|
-
const isTriad = chord.intervals.length === 3 && chord.intervals.some((interval) =>
|
|
758
|
-
return isTriad &&
|
|
757
|
+
const isTriad = chord.intervals.length === 3 && chord.intervals.some((interval) => _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, interval) === 7);
|
|
758
|
+
return isTriad && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.bassPc - chord.rootPc) === 7;
|
|
759
759
|
}
|
|
760
760
|
function isCadentialSixFour(chord, next, key) {
|
|
761
|
-
return isTonicSixFour(chord, key) &&
|
|
761
|
+
return isTonicSixFour(chord, key) && _chunk3R3QVKY5cjs.isDominantChordOf.call(void 0, next, key) && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, _nullishCoalesce(chord.bassPc, () => ( chord.rootPc))) === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, _nullishCoalesce(next.bassPc, () => ( next.rootPc)));
|
|
762
762
|
}
|
|
763
763
|
function outerPitches(voicing) {
|
|
764
764
|
let bass;
|
|
@@ -777,20 +777,20 @@ function outerPitches(voicing) {
|
|
|
777
777
|
return { bass, soprano };
|
|
778
778
|
}
|
|
779
779
|
function bassPcOf2(chord, voicedBass) {
|
|
780
|
-
return
|
|
780
|
+
return _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, _nullishCoalesce(_nullishCoalesce(voicedBass, () => ( chord.bassPc)), () => ( chord.rootPc)));
|
|
781
781
|
}
|
|
782
782
|
function cadenceType(from, to, key, fromBassPc, toBassPc) {
|
|
783
|
-
const tonic =
|
|
784
|
-
const fromOffset =
|
|
785
|
-
const toOffset =
|
|
786
|
-
const dominant =
|
|
787
|
-
if ((dominant ||
|
|
783
|
+
const tonic = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
784
|
+
const fromOffset = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, from.rootPc - tonic);
|
|
785
|
+
const toOffset = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, to.rootPc - tonic);
|
|
786
|
+
const dominant = _chunk3R3QVKY5cjs.isDominantChordOf.call(void 0, from, key);
|
|
787
|
+
if ((dominant || _chunk3R3QVKY5cjs.isLeadingToneChordOf.call(void 0, from, key)) && toOffset === 0) {
|
|
788
788
|
return "authentic";
|
|
789
789
|
}
|
|
790
790
|
if (fromOffset === degreeOffset(SUBDOMINANT_DEGREE, key) && toOffset === 0) {
|
|
791
791
|
return "plagal";
|
|
792
792
|
}
|
|
793
|
-
if (fromOffset === 10 && toOffset === 0 &&
|
|
793
|
+
if (fromOffset === 10 && toOffset === 0 && _chunk3R3QVKY5cjs.hasMajorThird.call(void 0, from)) {
|
|
794
794
|
return "modal";
|
|
795
795
|
}
|
|
796
796
|
if (dominant && deceptiveTargets(key).includes(toOffset)) {
|
|
@@ -798,7 +798,7 @@ function cadenceType(from, to, key, fromBassPc, toBassPc) {
|
|
|
798
798
|
}
|
|
799
799
|
const dominantOffset = degreeOffset(DOMINANT_DEGREE, key);
|
|
800
800
|
const half = toOffset === dominantOffset && restsOnDominant(to, key) && fromOffset !== dominantOffset;
|
|
801
|
-
if (half && isMinorScale(key) && fromOffset === 5 &&
|
|
801
|
+
if (half && isMinorScale(key) && fromOffset === 5 && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, fromBassPc - tonic) === 8 && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, toBassPc - tonic) === 7) {
|
|
802
802
|
return "phrygian";
|
|
803
803
|
}
|
|
804
804
|
return half ? "half" : null;
|
|
@@ -900,12 +900,12 @@ function cadenceAlternatives(facts) {
|
|
|
900
900
|
return out;
|
|
901
901
|
}
|
|
902
902
|
function detectCadence(from, to, key, opts = {}) {
|
|
903
|
-
const { approach, ...rest } =
|
|
903
|
+
const { approach, ...rest } = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
|
|
904
904
|
return cadenceBetween(
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
approach === void 0 ? rest : { ...rest, approach:
|
|
905
|
+
_chunk3R3QVKY5cjs.toChordData.call(void 0, from),
|
|
906
|
+
_chunk3R3QVKY5cjs.toChordData.call(void 0, to),
|
|
907
|
+
_chunk3R3QVKY5cjs.toKeyScale.call(void 0, key),
|
|
908
|
+
approach === void 0 ? rest : { ...rest, approach: _chunk3R3QVKY5cjs.toChordData.call(void 0, approach) }
|
|
909
909
|
);
|
|
910
910
|
}
|
|
911
911
|
function cadenceBetween(from, to, key, opts = {}) {
|
|
@@ -914,11 +914,11 @@ function cadenceBetween(from, to, key, opts = {}) {
|
|
|
914
914
|
const toOuter = outerPitches(_nullishCoalesce(toVoicing, () => ( [])));
|
|
915
915
|
const fromBassPc = bassPcOf2(from, fromOuter.bass);
|
|
916
916
|
const toBassPc = bassPcOf2(to, toOuter.bass);
|
|
917
|
-
const toRootPosition = toBassPc ===
|
|
918
|
-
const rootPosition = fromBassPc ===
|
|
919
|
-
const soprano = toOuter.soprano === void 0 ? null :
|
|
917
|
+
const toRootPosition = toBassPc === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, to.rootPc);
|
|
918
|
+
const rootPosition = fromBassPc === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, from.rootPc) && toRootPosition;
|
|
919
|
+
const soprano = toOuter.soprano === void 0 ? null : _chunk3R3QVKY5cjs.chordToneRole.call(void 0, toOuter.soprano, to);
|
|
920
920
|
const type = cadenceType(from, to, key, fromBassPc, toBassPc);
|
|
921
|
-
const leadingTone =
|
|
921
|
+
const leadingTone = _chunk3R3QVKY5cjs.isLeadingToneChordOf.call(void 0, from, key);
|
|
922
922
|
const facts = {
|
|
923
923
|
type,
|
|
924
924
|
strength: type === "authentic" ? authenticStrength(leadingTone, rootPosition, toOuter.soprano !== void 0, soprano) : null,
|
|
@@ -927,10 +927,10 @@ function cadenceBetween(from, to, key, opts = {}) {
|
|
|
927
927
|
// promised is the one it does not get.
|
|
928
928
|
evaded: type === "authentic" && !toRootPosition,
|
|
929
929
|
leadingTone,
|
|
930
|
-
fromOffset:
|
|
931
|
-
toOffset:
|
|
930
|
+
fromOffset: _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, from.rootPc - key.rootPc),
|
|
931
|
+
toOffset: _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, to.rootPc - key.rootPc),
|
|
932
932
|
minor: isMinorScale(key),
|
|
933
|
-
onFifthDegree:
|
|
933
|
+
onFifthDegree: _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, to.rootPc - key.rootPc) === degreeOffset(DOMINANT_DEGREE, key),
|
|
934
934
|
sixFour: opts.approach !== void 0 && isCadentialSixFour(opts.approach, from, key),
|
|
935
935
|
withinSixFour: isCadentialSixFour(from, to, key)
|
|
936
936
|
};
|
|
@@ -951,53 +951,53 @@ function cadenceBetween(from, to, key, opts = {}) {
|
|
|
951
951
|
// src/analyze/functional/borrowed.ts
|
|
952
952
|
function isMinorScaleAlteration(chord, key) {
|
|
953
953
|
if (!isMinorScale(key)) return false;
|
|
954
|
-
const alteredKey = { rootPc:
|
|
955
|
-
if (
|
|
956
|
-
return
|
|
954
|
+
const alteredKey = { rootPc: _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunk3R3QVKY5cjs.HARMONIC_MINOR_MASK };
|
|
955
|
+
if (_chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, alteredKey)) return true;
|
|
956
|
+
return _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc) === 11 && _chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, { rootPc: _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunk3R3QVKY5cjs.MELODIC_MINOR_MASK });
|
|
957
957
|
}
|
|
958
958
|
function isBorrowed(chord, key) {
|
|
959
|
-
if (
|
|
959
|
+
if (_chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, key)) {
|
|
960
960
|
return false;
|
|
961
961
|
}
|
|
962
|
-
if (
|
|
962
|
+
if (_chunk3R3QVKY5cjs.isNeapolitanChordOf.call(void 0, chord, key)) {
|
|
963
963
|
return true;
|
|
964
964
|
}
|
|
965
965
|
if (isMinorScaleAlteration(chord, key)) {
|
|
966
966
|
return false;
|
|
967
967
|
}
|
|
968
|
-
return
|
|
968
|
+
return _chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, parallelScale(key));
|
|
969
969
|
}
|
|
970
970
|
function borrowedSourceOf(chord, key) {
|
|
971
|
-
if (
|
|
971
|
+
if (_chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, key)) {
|
|
972
972
|
return null;
|
|
973
973
|
}
|
|
974
|
-
if (
|
|
974
|
+
if (_chunk3R3QVKY5cjs.isNeapolitanChordOf.call(void 0, chord, key)) return "neapolitan";
|
|
975
975
|
if (isBorrowed(chord, key)) {
|
|
976
976
|
return isMinorScale(key) ? "parallelMajor" : "parallelMinor";
|
|
977
977
|
}
|
|
978
978
|
return null;
|
|
979
979
|
}
|
|
980
980
|
function isBorrowedChord(chord, key) {
|
|
981
|
-
return isBorrowed(
|
|
981
|
+
return isBorrowed(_chunk3R3QVKY5cjs.toChordData.call(void 0, chord), _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key));
|
|
982
982
|
}
|
|
983
983
|
function borrowedSource(chord, key) {
|
|
984
|
-
return borrowedSourceOf(
|
|
984
|
+
return borrowedSourceOf(_chunk3R3QVKY5cjs.toChordData.call(void 0, chord), _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key));
|
|
985
985
|
}
|
|
986
986
|
|
|
987
987
|
// src/analyze/functional/tonicization.ts
|
|
988
988
|
function isTonicizableRoot(rootPc, key) {
|
|
989
|
-
return
|
|
989
|
+
return _chunk3R3QVKY5cjs.tonicizableDegrees.call(void 0, key).some((degree) => degree.rootPc === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc));
|
|
990
990
|
}
|
|
991
991
|
function appliedTarget(chord, key) {
|
|
992
|
-
const dominant =
|
|
993
|
-
const leadingTone =
|
|
992
|
+
const dominant = _chunk3R3QVKY5cjs.hasDominantSonority.call(void 0, chord);
|
|
993
|
+
const leadingTone = _chunk3R3QVKY5cjs.LEADING_TONE_QUALITIES.has(chord.quality);
|
|
994
994
|
if (!dominant && !leadingTone) {
|
|
995
995
|
return null;
|
|
996
996
|
}
|
|
997
|
-
return
|
|
997
|
+
return _chunk3R3QVKY5cjs.appliedDominantTarget.call(void 0, chord.rootPc + (dominant ? 5 : 1), key);
|
|
998
998
|
}
|
|
999
999
|
function isAppliedDominant(chord, key) {
|
|
1000
|
-
if (
|
|
1000
|
+
if (_chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, key)) {
|
|
1001
1001
|
return false;
|
|
1002
1002
|
}
|
|
1003
1003
|
const source = borrowedSourceOf(chord, key);
|
|
@@ -1010,7 +1010,7 @@ function pointsAtTonicizableDegree(chord, key) {
|
|
|
1010
1010
|
if (appliedTarget(chord, key) !== null) {
|
|
1011
1011
|
return true;
|
|
1012
1012
|
}
|
|
1013
|
-
return
|
|
1013
|
+
return _chunk3R3QVKY5cjs.soundsDominantSeventh.call(void 0, chord) && isTonicizableRoot(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc - 1), key);
|
|
1014
1014
|
}
|
|
1015
1015
|
|
|
1016
1016
|
// src/analyze/functional/roman.ts
|
|
@@ -1125,33 +1125,33 @@ function parseInversion(figures) {
|
|
|
1125
1125
|
function parseSimpleRoman(text, key) {
|
|
1126
1126
|
const match = /^([b#]?)([iIvV]+)(.*)$/.exec(text.trim());
|
|
1127
1127
|
if (!match) {
|
|
1128
|
-
throw new (0,
|
|
1128
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`Invalid Roman numeral: ${text}`);
|
|
1129
1129
|
}
|
|
1130
1130
|
const glyphText = _nullishCoalesce(match[2], () => ( ""));
|
|
1131
1131
|
if (glyphText !== glyphText.toUpperCase() && glyphText !== glyphText.toLowerCase()) {
|
|
1132
|
-
throw new (0,
|
|
1132
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`Roman numeral must use one case: ${text}`);
|
|
1133
1133
|
}
|
|
1134
1134
|
const accidental = match[1] === "b" ? -1 : match[1] === "#" ? 1 : 0;
|
|
1135
1135
|
const glyph = glyphText.toUpperCase();
|
|
1136
1136
|
const degreeNumber = ROMAN_TO_DEGREE[glyph];
|
|
1137
1137
|
if (degreeNumber === void 0) {
|
|
1138
|
-
throw new (0,
|
|
1138
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`Invalid Roman numeral: ${text}`);
|
|
1139
1139
|
}
|
|
1140
1140
|
const isUpper = glyphText[0] === _optionalChain([glyphText, 'access', _5 => _5[0], 'optionalAccess', _6 => _6.toUpperCase, 'call', _7 => _7()]);
|
|
1141
1141
|
const suffix = _nullishCoalesce(match[3], () => ( ""));
|
|
1142
1142
|
const frame = romanReference(key);
|
|
1143
1143
|
const redundantFlat = accidental === -1 && loweredDegrees(frame).has(degreeNumber);
|
|
1144
|
-
const diatonicRootPc =
|
|
1144
|
+
const diatonicRootPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0,
|
|
1145
1145
|
degreeRootPc(degreeNumber, frame) + (redundantFlat ? 0 : accidental)
|
|
1146
1146
|
);
|
|
1147
|
-
const rootForQuality = (quality2) => accidental === 0 && degreeNumber === 7 && loweredDegrees(frame).has(7) &&
|
|
1147
|
+
const rootForQuality = (quality2) => accidental === 0 && degreeNumber === 7 && loweredDegrees(frame).has(7) && _chunk3R3QVKY5cjs.LEADING_TONE_QUALITIES.has(quality2) ? _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, diatonicRootPc + 1) : diatonicRootPc;
|
|
1148
1148
|
const canonical = SUFFIX_QUALITY.get(`${isUpper ? "u" : "l"}:${suffix}`);
|
|
1149
1149
|
if (canonical !== void 0) {
|
|
1150
1150
|
return { rootPc: rootForQuality(canonical), quality: canonical, inversion: 0 };
|
|
1151
1151
|
}
|
|
1152
1152
|
const parsedSuffix = /^(o|°|dim|ø|\+|aug)?(maj7|M7)?(65|64|43|42|7|6|2)?$/.exec(suffix);
|
|
1153
1153
|
if (!parsedSuffix) {
|
|
1154
|
-
throw new (0,
|
|
1154
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`Unsupported suffix "${suffix}" in Roman numeral: ${text}`);
|
|
1155
1155
|
}
|
|
1156
1156
|
const qualityMarker = _nullishCoalesce(parsedSuffix[1], () => ( ""));
|
|
1157
1157
|
const isDim = qualityMarker === "o" || qualityMarker === "\xB0" || qualityMarker === "dim";
|
|
@@ -1160,7 +1160,7 @@ function parseSimpleRoman(text, key) {
|
|
|
1160
1160
|
const explicitMaj7 = parsedSuffix[2] !== void 0;
|
|
1161
1161
|
const figures = _nullishCoalesce(parsedSuffix[3], () => ( ""));
|
|
1162
1162
|
if (figures !== "" && !INVERSION_FIGURES.has(figures)) {
|
|
1163
|
-
throw new (0,
|
|
1163
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(
|
|
1164
1164
|
`Unsupported figured-bass or extension "${figures}" in Roman numeral: ${text}`
|
|
1165
1165
|
);
|
|
1166
1166
|
}
|
|
@@ -1191,22 +1191,22 @@ function parseSimpleRoman(text, key) {
|
|
|
1191
1191
|
var NEAPOLITAN_SIXTH = "N6";
|
|
1192
1192
|
function chromaticSymbolChord(text, key) {
|
|
1193
1193
|
if (text === NEAPOLITAN_SIXTH) {
|
|
1194
|
-
const rootPc =
|
|
1195
|
-
return
|
|
1194
|
+
const rootPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.scale.rootPc + 1);
|
|
1195
|
+
return _chunk3R3QVKY5cjs.makeChord.call(void 0, rootPc, "maj", _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc + 4));
|
|
1196
1196
|
}
|
|
1197
1197
|
return augmentedSixthFromSymbol(text, key);
|
|
1198
1198
|
}
|
|
1199
1199
|
function tonicizedKey(targetRoot, key) {
|
|
1200
|
-
return
|
|
1201
|
-
scale:
|
|
1202
|
-
tonic:
|
|
1200
|
+
return _chunk3R3QVKY5cjs.resolveKey.call(void 0, {
|
|
1201
|
+
scale: _chunk3R3QVKY5cjs.majorKey.call(void 0, targetRoot),
|
|
1202
|
+
tonic: _chunk3R3QVKY5cjs.spellPitchClass.call(void 0, targetRoot, key.tonic, key.scale)
|
|
1203
1203
|
});
|
|
1204
1204
|
}
|
|
1205
1205
|
function augmentedSixthTarget(chord, key) {
|
|
1206
|
-
if (
|
|
1206
|
+
if (_chunk3R3QVKY5cjs.chordToneSpellings.call(void 0, chord) === void 0) {
|
|
1207
1207
|
return null;
|
|
1208
1208
|
}
|
|
1209
|
-
for (const degree of
|
|
1209
|
+
for (const degree of _chunk3R3QVKY5cjs.tonicizableDegrees.call(void 0, key.scale)) {
|
|
1210
1210
|
if (degree.degreeNumber === 1) {
|
|
1211
1211
|
continue;
|
|
1212
1212
|
}
|
|
@@ -1217,14 +1217,14 @@ function augmentedSixthTarget(chord, key) {
|
|
|
1217
1217
|
return null;
|
|
1218
1218
|
}
|
|
1219
1219
|
function chordFromParsed(parsed) {
|
|
1220
|
-
const chord =
|
|
1220
|
+
const chord = _chunk3R3QVKY5cjs.makeChord.call(void 0, parsed.rootPc, parsed.quality);
|
|
1221
1221
|
if (parsed.inversion > 0 && parsed.inversion < chord.intervals.length) {
|
|
1222
|
-
chord.bassPc =
|
|
1222
|
+
chord.bassPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, parsed.rootPc + (_nullishCoalesce(chord.intervals[parsed.inversion], () => ( 0))));
|
|
1223
1223
|
}
|
|
1224
1224
|
return chord;
|
|
1225
1225
|
}
|
|
1226
1226
|
function romanToChord(text, key) {
|
|
1227
|
-
const resolved =
|
|
1227
|
+
const resolved = _chunk3R3QVKY5cjs.resolveKey.call(void 0, key);
|
|
1228
1228
|
const scale = resolved.scale;
|
|
1229
1229
|
const trimmed = text.trim().replace(/(\d)\/(?=\d)/g, "$1");
|
|
1230
1230
|
const slash = trimmed.indexOf("/");
|
|
@@ -1241,14 +1241,14 @@ function romanStyle(quality) {
|
|
|
1241
1241
|
return ROMAN_STYLE[quality];
|
|
1242
1242
|
}
|
|
1243
1243
|
function romanSpelling(rootPc, key) {
|
|
1244
|
-
const tones =
|
|
1245
|
-
const diatonic = tones.indexOf(
|
|
1244
|
+
const tones = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, romanReference(key));
|
|
1245
|
+
const diatonic = tones.indexOf(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc));
|
|
1246
1246
|
if (diatonic >= 0) {
|
|
1247
1247
|
return { degreeNumber: diatonic + 1, accidental: "" };
|
|
1248
1248
|
}
|
|
1249
1249
|
const lowered = loweredDegrees(romanReference(key));
|
|
1250
1250
|
for (let i = 0; i < tones.length; i += 1) {
|
|
1251
|
-
if (lowered.has(i + 1) &&
|
|
1251
|
+
if (lowered.has(i + 1) && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) + 1) === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
1252
1252
|
return { degreeNumber: i + 1, accidental: "#" };
|
|
1253
1253
|
}
|
|
1254
1254
|
}
|
|
@@ -1257,20 +1257,20 @@ function romanSpelling(rootPc, key) {
|
|
|
1257
1257
|
if (degreeNumber2 === 1 || degreeNumber2 === 5) {
|
|
1258
1258
|
continue;
|
|
1259
1259
|
}
|
|
1260
|
-
if (
|
|
1260
|
+
if (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) - 1) === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
1261
1261
|
return { degreeNumber: degreeNumber2, accidental: "b" };
|
|
1262
1262
|
}
|
|
1263
1263
|
}
|
|
1264
1264
|
for (let i = 0; i < tones.length; i += 1) {
|
|
1265
|
-
if (
|
|
1265
|
+
if (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) + 1) === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
1266
1266
|
return { degreeNumber: i + 1, accidental: "#" };
|
|
1267
1267
|
}
|
|
1268
1268
|
}
|
|
1269
|
-
const [degreeNumber, accidental] = _nullishCoalesce(OFFSET_SPELLING[
|
|
1269
|
+
const [degreeNumber, accidental] = _nullishCoalesce(OFFSET_SPELLING[_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc - key.rootPc)], () => ( [1, ""]));
|
|
1270
1270
|
return { degreeNumber, accidental };
|
|
1271
1271
|
}
|
|
1272
1272
|
function seventhDegreeAccidental(accidental, degreeNumber, quality, key) {
|
|
1273
|
-
if (degreeNumber !== 7 || !
|
|
1273
|
+
if (degreeNumber !== 7 || !_chunk3R3QVKY5cjs.LEADING_TONE_QUALITIES.has(quality) || !loweredDegrees(romanReference(key)).has(7)) {
|
|
1274
1274
|
return accidental;
|
|
1275
1275
|
}
|
|
1276
1276
|
if (accidental === "#") {
|
|
@@ -1312,22 +1312,22 @@ var SEVENTH_FIGURE_QUALITIES = /* @__PURE__ */ new Set([
|
|
|
1312
1312
|
function numeralFor(degreeNumber, lower) {
|
|
1313
1313
|
const glyph = ROMAN[degreeNumber - 1];
|
|
1314
1314
|
if (glyph === void 0) {
|
|
1315
|
-
throw new (0,
|
|
1315
|
+
throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`no Roman numeral for scale degree ${degreeNumber}`);
|
|
1316
1316
|
}
|
|
1317
1317
|
return lower ? glyph.toLowerCase() : glyph;
|
|
1318
1318
|
}
|
|
1319
1319
|
function chordToRoman(chord, key, opts = {}) {
|
|
1320
|
-
return renderRoman(
|
|
1320
|
+
return renderRoman(_chunk3R3QVKY5cjs.toChordData.call(void 0, chord), key, _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts")).roman;
|
|
1321
1321
|
}
|
|
1322
1322
|
function renderRoman(chord, keyLike, opts) {
|
|
1323
|
-
const resolved =
|
|
1323
|
+
const resolved = _chunk3R3QVKY5cjs.resolveKey.call(void 0, keyLike);
|
|
1324
1324
|
const key = resolved.scale;
|
|
1325
1325
|
const augmented = augmentedSixthSymbol(chord, resolved);
|
|
1326
1326
|
if (augmented !== null) {
|
|
1327
1327
|
return { roman: augmented, derivation: { kind: "augmentedSixth" } };
|
|
1328
1328
|
}
|
|
1329
1329
|
if (opts.applied === true) {
|
|
1330
|
-
const target = _nullishCoalesce(augmentedSixthTarget(chord, resolved), () => ( (
|
|
1330
|
+
const target = _nullishCoalesce(augmentedSixthTarget(chord, resolved), () => ( (_chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, key) ? null : appliedTarget(chord, key))));
|
|
1331
1331
|
if (target !== null) {
|
|
1332
1332
|
const local = renderRoman(chord, tonicizedKey(target.rootPc, resolved), {}).roman;
|
|
1333
1333
|
const numeral = numeralFor(target.degreeNumber, target.lower);
|
|
@@ -1344,14 +1344,14 @@ function renderRoman(chord, keyLike, opts) {
|
|
|
1344
1344
|
let inversion = 0;
|
|
1345
1345
|
let bass = "root";
|
|
1346
1346
|
if (chord.bassPc !== void 0) {
|
|
1347
|
-
const idx = chord.intervals.findIndex((iv) =>
|
|
1347
|
+
const idx = chord.intervals.findIndex((iv) => _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc + iv) === chord.bassPc);
|
|
1348
1348
|
if (idx > 0) {
|
|
1349
1349
|
inversion = idx;
|
|
1350
1350
|
} else if (idx < 0) {
|
|
1351
1351
|
bass = "foreign";
|
|
1352
1352
|
}
|
|
1353
1353
|
}
|
|
1354
|
-
if (opts.neapolitan === true && inversion === 1 &&
|
|
1354
|
+
if (opts.neapolitan === true && inversion === 1 && _chunk3R3QVKY5cjs.isNeapolitanChordOf.call(void 0, chord, key)) {
|
|
1355
1355
|
return { roman: NEAPOLITAN_SIXTH, derivation: { kind: "neapolitan" } };
|
|
1356
1356
|
}
|
|
1357
1357
|
if (inversion > 0) {
|
|
@@ -1450,8 +1450,8 @@ function romanAlternatives(chord, key, opts) {
|
|
|
1450
1450
|
return out;
|
|
1451
1451
|
}
|
|
1452
1452
|
function explainRoman(chord, key, opts = {}) {
|
|
1453
|
-
const asked =
|
|
1454
|
-
const data =
|
|
1453
|
+
const asked = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
|
|
1454
|
+
const data = _chunk3R3QVKY5cjs.toChordData.call(void 0, chord);
|
|
1455
1455
|
const { roman, derivation } = renderRoman(data, key, asked);
|
|
1456
1456
|
return {
|
|
1457
1457
|
roman,
|
|
@@ -1519,18 +1519,18 @@ var MINOR_FUNCTION_BY_OFFSET = [
|
|
|
1519
1519
|
// 11 viio
|
|
1520
1520
|
];
|
|
1521
1521
|
function isMinorKey(key) {
|
|
1522
|
-
return isMinorScale(
|
|
1522
|
+
return isMinorScale(_chunk3R3QVKY5cjs.toKeyScale.call(void 0, key));
|
|
1523
1523
|
}
|
|
1524
1524
|
function functionOf(chord, key) {
|
|
1525
|
-
return functionWithReason(
|
|
1525
|
+
return functionWithReason(_chunk3R3QVKY5cjs.toChordData.call(void 0, chord), _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key)).function;
|
|
1526
1526
|
}
|
|
1527
1527
|
function degreeFunction(chord, key) {
|
|
1528
1528
|
const functions = isMinorScale(key) ? MINOR_FUNCTION_BY_OFFSET : FUNCTION_BY_OFFSET;
|
|
1529
|
-
return _nullishCoalesce(functions[
|
|
1529
|
+
return _nullishCoalesce(functions[_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc)], () => ( "tonic"));
|
|
1530
1530
|
}
|
|
1531
1531
|
function functionWithReason(chord, key) {
|
|
1532
|
-
const offset =
|
|
1533
|
-
if (
|
|
1532
|
+
const offset = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc);
|
|
1533
|
+
if (_chunk3R3QVKY5cjs.isNeapolitanChordOf.call(void 0, chord, key)) {
|
|
1534
1534
|
return { function: "subdominant", reason: "neapolitan" };
|
|
1535
1535
|
}
|
|
1536
1536
|
if (augmentedSixthKindOf(chord, key) !== null) {
|
|
@@ -1539,7 +1539,7 @@ function functionWithReason(chord, key) {
|
|
|
1539
1539
|
if (isAppliedDominant(chord, key)) {
|
|
1540
1540
|
return { function: "dominant", reason: "applied" };
|
|
1541
1541
|
}
|
|
1542
|
-
if (!isMinorScale(key) && !
|
|
1542
|
+
if (!isMinorScale(key) && !_chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, key) && _chunk3R3QVKY5cjs.hasMajorThird.call(void 0, chord) && (offset === 8 || offset === 10)) {
|
|
1543
1543
|
return { function: "subdominant", reason: "flatSideMajor" };
|
|
1544
1544
|
}
|
|
1545
1545
|
return { function: degreeFunction(chord, key), reason: "degree" };
|
|
@@ -1562,7 +1562,7 @@ function describeChord(fn, reason, roman, source) {
|
|
|
1562
1562
|
function functionAlternatives(chord, key, reason, accepted) {
|
|
1563
1563
|
const out = [];
|
|
1564
1564
|
if (reason === "degree") {
|
|
1565
|
-
if (pointsAtTonicizableDegree(chord, key) &&
|
|
1565
|
+
if (pointsAtTonicizableDegree(chord, key) && _chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, key)) {
|
|
1566
1566
|
out.push({
|
|
1567
1567
|
label: "applied dominant",
|
|
1568
1568
|
reason: "The chord is diatonic to the key, so it keeps the function of its degree rather than tonicizing another"
|
|
@@ -1586,15 +1586,15 @@ function functionAlternatives(chord, key, reason, accepted) {
|
|
|
1586
1586
|
return out;
|
|
1587
1587
|
}
|
|
1588
1588
|
function isDiatonic(chord, key) {
|
|
1589
|
-
return
|
|
1589
|
+
return _chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, _chunk3R3QVKY5cjs.toChordData.call(void 0, chord), _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key));
|
|
1590
1590
|
}
|
|
1591
1591
|
function parallelKey(key) {
|
|
1592
|
-
return parallelScale(
|
|
1592
|
+
return parallelScale(_chunk3R3QVKY5cjs.toKeyScale.call(void 0, key));
|
|
1593
1593
|
}
|
|
1594
1594
|
function analyzeChord(chord, key, opts = {}) {
|
|
1595
|
-
const asked =
|
|
1596
|
-
const data =
|
|
1597
|
-
const scale =
|
|
1595
|
+
const asked = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
|
|
1596
|
+
const data = _chunk3R3QVKY5cjs.toChordData.call(void 0, chord);
|
|
1597
|
+
const scale = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key);
|
|
1598
1598
|
const source = borrowedSourceOf(data, scale);
|
|
1599
1599
|
const { function: fn, reason } = functionWithReason(data, scale);
|
|
1600
1600
|
const roman = renderRoman(data, scale, asked).roman;
|
|
@@ -1611,18 +1611,18 @@ function analyzeChord(chord, key, opts = {}) {
|
|
|
1611
1611
|
};
|
|
1612
1612
|
}
|
|
1613
1613
|
function secondaryDominant(targetDegree, key) {
|
|
1614
|
-
const scale =
|
|
1615
|
-
const degreeCount =
|
|
1616
|
-
|
|
1614
|
+
const scale = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key);
|
|
1615
|
+
const degreeCount = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, scale).length;
|
|
1616
|
+
_chunkS5BKZZGMcjs.assertInteger.call(void 0, targetDegree, "targetDegree", 1, degreeCount);
|
|
1617
1617
|
const targetRoot = degreeRootPc(targetDegree, scale);
|
|
1618
|
-
return
|
|
1618
|
+
return _chunk3R3QVKY5cjs.makeChord.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, targetRoot + 7), "dom7");
|
|
1619
1619
|
}
|
|
1620
1620
|
function secondaryDominantOf(target) {
|
|
1621
|
-
const data =
|
|
1622
|
-
|
|
1623
|
-
const dominant =
|
|
1621
|
+
const data = _chunk3R3QVKY5cjs.toChordData.call(void 0, target);
|
|
1622
|
+
_chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, data.rootPc, "target chord rootPc");
|
|
1623
|
+
const dominant = _chunk3R3QVKY5cjs.makeChord.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, data.rootPc + 7), "dom7");
|
|
1624
1624
|
if (data.rootSpelling !== void 0) {
|
|
1625
|
-
const moved =
|
|
1625
|
+
const moved = _chunkS5BKZZGMcjs.transposeNote.call(void 0, data.rootSpelling, 7);
|
|
1626
1626
|
dominant.rootSpelling = { letter: moved.letter, alter: moved.alter };
|
|
1627
1627
|
}
|
|
1628
1628
|
return dominant;
|
|
@@ -1631,17 +1631,17 @@ function secondaryDominantOf(target) {
|
|
|
1631
1631
|
// src/analyze/functional/pivot.ts
|
|
1632
1632
|
var HEPTATONIC_DEGREES = 7;
|
|
1633
1633
|
function pivotChords(from, to) {
|
|
1634
|
-
return pivotsBetween(
|
|
1634
|
+
return pivotsBetween(_chunk3R3QVKY5cjs.toKeyScale.call(void 0, from), _chunk3R3QVKY5cjs.toKeyScale.call(void 0, to));
|
|
1635
1635
|
}
|
|
1636
1636
|
function pivotsBetween(from, to) {
|
|
1637
|
-
if (
|
|
1637
|
+
if (_chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, from).length !== HEPTATONIC_DEGREES) {
|
|
1638
1638
|
return [];
|
|
1639
1639
|
}
|
|
1640
1640
|
const pivots = [];
|
|
1641
1641
|
const seen = /* @__PURE__ */ new Set();
|
|
1642
1642
|
for (let degree = 1; degree <= HEPTATONIC_DEGREES; degree += 1) {
|
|
1643
1643
|
const chord = stackedTriad(degree, from);
|
|
1644
|
-
if (chord === null || !
|
|
1644
|
+
if (chord === null || !_chunk3R3QVKY5cjs.isDiatonicChord.call(void 0, chord, to)) {
|
|
1645
1645
|
continue;
|
|
1646
1646
|
}
|
|
1647
1647
|
const identity = `${chord.rootPc}:${chord.quality}`;
|
|
@@ -1659,9 +1659,9 @@ function pivotsBetween(from, to) {
|
|
|
1659
1659
|
}
|
|
1660
1660
|
function stackedTriad(degree, key) {
|
|
1661
1661
|
try {
|
|
1662
|
-
return
|
|
1662
|
+
return _chunk3R3QVKY5cjs.diatonicTriad.call(void 0, degree, key);
|
|
1663
1663
|
} catch (error) {
|
|
1664
|
-
if (error instanceof
|
|
1664
|
+
if (error instanceof _chunkS5BKZZGMcjs.InvalidInputError) {
|
|
1665
1665
|
return null;
|
|
1666
1666
|
}
|
|
1667
1667
|
throw error;
|
|
@@ -1683,34 +1683,34 @@ function firstSoundingBeat(notes, fallback = 0) {
|
|
|
1683
1683
|
return Number.isFinite(first) ? first : fallback;
|
|
1684
1684
|
}
|
|
1685
1685
|
function lastBarOf(meter, spanStart, spanEnd) {
|
|
1686
|
-
const firstBar =
|
|
1687
|
-
const bar =
|
|
1688
|
-
if (bar > firstBar &&
|
|
1686
|
+
const firstBar = _chunkS5BKZZGMcjs.barIndexAt.call(void 0, spanStart, meter);
|
|
1687
|
+
const bar = _chunkS5BKZZGMcjs.barIndexAt.call(void 0, Math.max(spanStart, spanEnd), meter);
|
|
1688
|
+
if (bar > firstBar && _chunkS5BKZZGMcjs.barPositionToBeat.call(void 0, { bar, beat: 0 }, meter) >= spanEnd - _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
1689
1689
|
return bar - 1;
|
|
1690
1690
|
}
|
|
1691
1691
|
return bar;
|
|
1692
1692
|
}
|
|
1693
1693
|
function sliceBars(notes, meter, spanStart, spanEnd, budget) {
|
|
1694
|
-
const firstBar =
|
|
1694
|
+
const firstBar = _chunkS5BKZZGMcjs.barIndexAt.call(void 0, spanStart, meter);
|
|
1695
1695
|
const lastBar = lastBarOf(meter, spanStart, spanEnd);
|
|
1696
1696
|
const barCount = lastBar - firstBar + 1;
|
|
1697
|
-
|
|
1697
|
+
_chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, barCount, "form bars", budget);
|
|
1698
1698
|
const buckets = Array.from({ length: barCount }, () => []);
|
|
1699
1699
|
let memberships = 0;
|
|
1700
1700
|
for (const note of notes) {
|
|
1701
1701
|
const noteEnd = note.startBeat + note.durationBeat;
|
|
1702
|
-
const from = Math.max(firstBar,
|
|
1703
|
-
const to = Math.min(lastBar,
|
|
1702
|
+
const from = Math.max(firstBar, _chunkS5BKZZGMcjs.barIndexAt.call(void 0, note.startBeat, meter));
|
|
1703
|
+
const to = Math.min(lastBar, _chunkS5BKZZGMcjs.barIndexAt.call(void 0, Math.max(note.startBeat, noteEnd - _chunkS5BKZZGMcjs.BEAT_EPS), meter));
|
|
1704
1704
|
memberships += Math.max(0, to - from + 1);
|
|
1705
|
-
|
|
1705
|
+
_chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, memberships, "form note-to-bar memberships", budget);
|
|
1706
1706
|
for (let bar = from; bar <= to; bar += 1) {
|
|
1707
1707
|
_optionalChain([buckets, 'access', _8 => _8[bar - firstBar], 'optionalAccess', _9 => _9.push, 'call', _10 => _10(note)]);
|
|
1708
1708
|
}
|
|
1709
1709
|
}
|
|
1710
1710
|
const slices = [];
|
|
1711
1711
|
for (let bar = firstBar; bar <= lastBar; bar += 1) {
|
|
1712
|
-
const startBeat =
|
|
1713
|
-
const endBeat =
|
|
1712
|
+
const startBeat = _chunkS5BKZZGMcjs.barPositionToBeat.call(void 0, { bar, beat: 0 }, meter);
|
|
1713
|
+
const endBeat = _chunkS5BKZZGMcjs.barPositionToBeat.call(void 0, { bar: bar + 1, beat: 0 }, meter);
|
|
1714
1714
|
const barNotes = _nullishCoalesce(buckets[bar - firstBar], () => ( []));
|
|
1715
1715
|
const { weights, totalWeight } = windowWeights(barNotes, startBeat, endBeat, meter);
|
|
1716
1716
|
slices.push({ index: bar, startBeat, endBeat, notes: barNotes, weights, totalWeight });
|
|
@@ -1728,10 +1728,10 @@ function weightSimilarity(a, b) {
|
|
|
1728
1728
|
normA += x * x;
|
|
1729
1729
|
normB += y * y;
|
|
1730
1730
|
}
|
|
1731
|
-
if (normA <=
|
|
1731
|
+
if (normA <= _chunkS5BKZZGMcjs.BEAT_EPS && normB <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
1732
1732
|
return 1;
|
|
1733
1733
|
}
|
|
1734
|
-
if (normA <=
|
|
1734
|
+
if (normA <= _chunkS5BKZZGMcjs.BEAT_EPS || normB <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
1735
1735
|
return 0;
|
|
1736
1736
|
}
|
|
1737
1737
|
return clamp01(dot / Math.sqrt(normA * normB));
|
|
@@ -1758,13 +1758,13 @@ function combineEvidence(strengths) {
|
|
|
1758
1758
|
// src/analyze/grid.ts
|
|
1759
1759
|
function gridOriginOf(firstOnset, slotBeats) {
|
|
1760
1760
|
const startBeat = firstOnset < 0 && firstOnset > -HUMANIZE_ADJACENCY ? 0 : firstOnset;
|
|
1761
|
-
return { origin: Math.floor(startBeat / slotBeats +
|
|
1761
|
+
return { origin: Math.floor(startBeat / slotBeats + _chunkS5BKZZGMcjs.BEAT_EPS) * slotBeats, startBeat };
|
|
1762
1762
|
}
|
|
1763
1763
|
function gridForNotes(notes, slotBeats) {
|
|
1764
1764
|
return gridOriginOf(firstSoundingBeat(notes), slotBeats);
|
|
1765
1765
|
}
|
|
1766
1766
|
function barGridStart(firstOnset, meter) {
|
|
1767
|
-
return gridOriginOf(firstOnset,
|
|
1767
|
+
return gridOriginOf(firstOnset, _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, firstOnset, meter)).startBeat;
|
|
1768
1768
|
}
|
|
1769
1769
|
|
|
1770
1770
|
// src/analyze/keys/index.ts
|
|
@@ -1784,13 +1784,13 @@ var FIFTHS_DISTANCE_COST = 0.18;
|
|
|
1784
1784
|
var KEY_CANDIDATES = (() => {
|
|
1785
1785
|
const candidates = [];
|
|
1786
1786
|
for (let rootPc = 0; rootPc < 12; rootPc += 1) {
|
|
1787
|
-
candidates.push({ key:
|
|
1788
|
-
candidates.push({ key:
|
|
1787
|
+
candidates.push({ key: _chunk3R3QVKY5cjs.majorKey.call(void 0, rootPc), rootPc, minor: false });
|
|
1788
|
+
candidates.push({ key: _chunk3R3QVKY5cjs.minorKey.call(void 0, rootPc), rootPc, minor: true });
|
|
1789
1789
|
}
|
|
1790
1790
|
return candidates;
|
|
1791
1791
|
})();
|
|
1792
1792
|
function fifthsOf(rootPc, minor) {
|
|
1793
|
-
const majorRoot =
|
|
1793
|
+
const majorRoot = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, minor ? rootPc + 3 : rootPc);
|
|
1794
1794
|
const raw = majorRoot * 7 % 12;
|
|
1795
1795
|
return raw > 6 ? raw - 12 : raw;
|
|
1796
1796
|
}
|
|
@@ -1808,9 +1808,9 @@ function chooseKeys(slots, changeCost, meter, budget) {
|
|
|
1808
1808
|
if (slots.length === 0) {
|
|
1809
1809
|
return [];
|
|
1810
1810
|
}
|
|
1811
|
-
const back =
|
|
1812
|
-
let costs =
|
|
1813
|
-
let spare =
|
|
1811
|
+
const back = _chunkS5BKZZGMcjs.allocateChoiceTable.call(void 0, slots.length, count, "key search choices", budget);
|
|
1812
|
+
let costs = _chunkS5BKZZGMcjs.allocateCandidateTable.call(void 0, 1, count, "key search costs", budget);
|
|
1813
|
+
let spare = _chunkS5BKZZGMcjs.allocateCandidateTable.call(void 0, 1, count, "key search costs", budget);
|
|
1814
1814
|
const opening = _nullishCoalesce(_optionalChain([slots, 'access', _11 => _11[0], 'optionalAccess', _12 => _12.scores]), () => ( []));
|
|
1815
1815
|
for (let c = 0; c < count; c += 1) {
|
|
1816
1816
|
costs[c] = -(_nullishCoalesce(opening[c], () => ( 0)));
|
|
@@ -1819,7 +1819,7 @@ function chooseKeys(slots, changeCost, meter, budget) {
|
|
|
1819
1819
|
const slot = slots[i];
|
|
1820
1820
|
const previous = costs;
|
|
1821
1821
|
const next = spare;
|
|
1822
|
-
const accent =
|
|
1822
|
+
const accent = _chunkS5BKZZGMcjs.metricWeight.call(void 0, _nullishCoalesce(_optionalChain([slot, 'optionalAccess', _13 => _13.startBeat]), () => ( 0)), meter);
|
|
1823
1823
|
const metricFactor = 1 - STRONG_BEAT_DISCOUNT * accent / MAX_METRIC_WEIGHT;
|
|
1824
1824
|
const rowBase = i * count;
|
|
1825
1825
|
for (let to = 0; to < count; to += 1) {
|
|
@@ -1889,7 +1889,7 @@ function enforceMinimumRegion(slots, path, minBeats, budget) {
|
|
|
1889
1889
|
return chosen;
|
|
1890
1890
|
}
|
|
1891
1891
|
const candidates = KEY_CANDIDATES.length;
|
|
1892
|
-
const totals =
|
|
1892
|
+
const totals = _chunkS5BKZZGMcjs.allocateCandidateTable.call(void 0, slots.length, candidates, "key region scores", budget);
|
|
1893
1893
|
for (let i = 0; i < slots.length; i += 1) {
|
|
1894
1894
|
const scores = _nullishCoalesce(_optionalChain([slots, 'access', _18 => _18[i], 'optionalAccess', _19 => _19.scores]), () => ( []));
|
|
1895
1895
|
const base = i * candidates;
|
|
@@ -1920,13 +1920,13 @@ function enforceMinimumRegion(slots, path, minBeats, budget) {
|
|
|
1920
1920
|
return chosen;
|
|
1921
1921
|
}
|
|
1922
1922
|
const length = region.endBeat - region.startBeat;
|
|
1923
|
-
if (region.merged || length >= minBeats -
|
|
1923
|
+
if (region.merged || length >= minBeats - _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
1924
1924
|
continue;
|
|
1925
1925
|
}
|
|
1926
1926
|
const previous = region.previous;
|
|
1927
1927
|
const next = region.next;
|
|
1928
|
-
const before = previous !== void 0 && Math.abs(previous.endBeat - region.startBeat) <
|
|
1929
|
-
const after = next !== void 0 && Math.abs(next.startBeat - region.endBeat) <
|
|
1928
|
+
const before = previous !== void 0 && Math.abs(previous.endBeat - region.startBeat) < _chunkS5BKZZGMcjs.BEAT_EPS ? previous : void 0;
|
|
1929
|
+
const after = next !== void 0 && Math.abs(next.startBeat - region.endBeat) < _chunkS5BKZZGMcjs.BEAT_EPS ? next : void 0;
|
|
1930
1930
|
if (before === void 0 && after === void 0) {
|
|
1931
1931
|
continue;
|
|
1932
1932
|
}
|
|
@@ -2036,7 +2036,7 @@ function withRelations(regions) {
|
|
|
2036
2036
|
if (previous === void 0 || current === void 0) {
|
|
2037
2037
|
continue;
|
|
2038
2038
|
}
|
|
2039
|
-
const relation =
|
|
2039
|
+
const relation = _chunk3R3QVKY5cjs.keyRelationBetween.call(void 0, previous.key, current.key);
|
|
2040
2040
|
if (relation !== null && relation !== "same") {
|
|
2041
2041
|
current.modulation = relation;
|
|
2042
2042
|
}
|
|
@@ -2044,22 +2044,22 @@ function withRelations(regions) {
|
|
|
2044
2044
|
return regions;
|
|
2045
2045
|
}
|
|
2046
2046
|
function keyTimelineFromNotes(notes, opts = {}) {
|
|
2047
|
-
const meters =
|
|
2048
|
-
const bar =
|
|
2047
|
+
const meters = _chunkS5BKZZGMcjs.resolveMeters.call(void 0, opts, "key timeline meters");
|
|
2048
|
+
const bar = _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, 0, meters);
|
|
2049
2049
|
const expectedKeyBeats = _nullishCoalesce(opts.expectedKeyBeats, () => ( bar * 4));
|
|
2050
|
-
|
|
2050
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, expectedKeyBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "expectedKeyBeats");
|
|
2051
2051
|
const minKeyBeats = _nullishCoalesce(opts.minKeyBeats, () => ( bar));
|
|
2052
|
-
|
|
2052
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, minKeyBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "minKeyBeats");
|
|
2053
2053
|
const budget = opts.budget;
|
|
2054
|
-
|
|
2054
|
+
_chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, notes, "key timeline notes", { allowNonPositiveDuration: true, budget });
|
|
2055
2055
|
const sounding = notes.filter((note) => note.durationBeat > 0);
|
|
2056
2056
|
const lastEnd = sounding.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), 0);
|
|
2057
2057
|
const totalBeats = _nullishCoalesce(opts.totalBeats, () => ( lastEnd));
|
|
2058
|
-
|
|
2058
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, totalBeats, 0, Number.MAX_SAFE_INTEGER, "key timeline totalBeats");
|
|
2059
2059
|
const slotBeats = Math.min(minKeyBeats, expectedKeyBeats);
|
|
2060
2060
|
const { origin, startBeat: musicStart } = gridForNotes(sounding, slotBeats);
|
|
2061
|
-
const slotCount = Math.max(0, Math.ceil((totalBeats - origin) / slotBeats -
|
|
2062
|
-
|
|
2061
|
+
const slotCount = Math.max(0, Math.ceil((totalBeats - origin) / slotBeats - _chunkS5BKZZGMcjs.BEAT_EPS));
|
|
2062
|
+
_chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, slotCount * KEY_CANDIDATES.length, "key timeline slots", budget);
|
|
2063
2063
|
if (slotCount === 0 || sounding.length === 0) {
|
|
2064
2064
|
return [];
|
|
2065
2065
|
}
|
|
@@ -2097,7 +2097,7 @@ function keyTimelineFromNotes(notes, opts = {}) {
|
|
|
2097
2097
|
(candidate) => profileScore(weights, candidate.minor ? profile.minor : profile.major, candidate.rootPc) * totalWeight
|
|
2098
2098
|
);
|
|
2099
2099
|
slots.push({ startBeat, endBeat, scores, weight: totalWeight });
|
|
2100
|
-
if (totalWeight >
|
|
2100
|
+
if (totalWeight > _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2101
2101
|
weightSum += totalWeight;
|
|
2102
2102
|
soundingSlots += 1;
|
|
2103
2103
|
}
|
|
@@ -2111,14 +2111,14 @@ function keyTimelineFromNotes(notes, opts = {}) {
|
|
|
2111
2111
|
const grouped = regionsFromPath(slots, path);
|
|
2112
2112
|
const head = grouped[0];
|
|
2113
2113
|
const next = grouped[1];
|
|
2114
|
-
if (head !== void 0 && next !== void 0 && head.endBeat - Math.max(head.startBeat, musicStart) < slotBeats -
|
|
2114
|
+
if (head !== void 0 && next !== void 0 && head.endBeat - Math.max(head.startBeat, musicStart) < slotBeats - _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2115
2115
|
next.startBeat = head.startBeat;
|
|
2116
2116
|
next.from = head.from;
|
|
2117
2117
|
grouped.shift();
|
|
2118
2118
|
}
|
|
2119
2119
|
const regions = grouped.map((region) => {
|
|
2120
2120
|
const candidate = KEY_CANDIDATES[region.candidate];
|
|
2121
|
-
const key =
|
|
2121
|
+
const key = _chunk3R3QVKY5cjs.resolveKey.call(void 0, _nullishCoalesce(_optionalChain([candidate, 'optionalAccess', _24 => _24.key]), () => ( _chunk3R3QVKY5cjs.majorKey.call(void 0, 0))));
|
|
2122
2122
|
const startBeat = Math.max(region.startBeat, musicStart);
|
|
2123
2123
|
const weights = new Array(PITCH_CLASSES).fill(0);
|
|
2124
2124
|
for (let i = region.from; i < region.toExclusive; i += 1) {
|
|
@@ -2138,7 +2138,7 @@ function keyTimelineFromNotes(notes, opts = {}) {
|
|
|
2138
2138
|
return {
|
|
2139
2139
|
startBeat,
|
|
2140
2140
|
endBeat: region.endBeat,
|
|
2141
|
-
key:
|
|
2141
|
+
key: _chunk3R3QVKY5cjs.resolveKey.call(void 0, key),
|
|
2142
2142
|
confidence: Math.max(0, correlation)
|
|
2143
2143
|
};
|
|
2144
2144
|
});
|
|
@@ -2150,20 +2150,20 @@ var TONIC_CREDIT = 0.4;
|
|
|
2150
2150
|
var CADENCE_CREDIT = 0.6;
|
|
2151
2151
|
var CHORD_MODULATION_COST = 0.6;
|
|
2152
2152
|
function chordFitsKey(chord, candidate) {
|
|
2153
|
-
const tones =
|
|
2153
|
+
const tones = _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord);
|
|
2154
2154
|
if (tones.length === 0) {
|
|
2155
2155
|
return 0;
|
|
2156
2156
|
}
|
|
2157
2157
|
let inKey = 0;
|
|
2158
2158
|
for (const pc of tones) {
|
|
2159
|
-
if (
|
|
2159
|
+
if (_chunk3R3QVKY5cjs.isScaleTone.call(void 0, pc, candidate.key)) {
|
|
2160
2160
|
inKey += 1;
|
|
2161
2161
|
}
|
|
2162
2162
|
}
|
|
2163
2163
|
let score = CHORD_TONE_CREDIT * ((inKey - (tones.length - inKey)) / tones.length);
|
|
2164
|
-
const rootDegree =
|
|
2164
|
+
const rootDegree = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc - candidate.rootPc);
|
|
2165
2165
|
if (rootDegree === 7) {
|
|
2166
|
-
if (
|
|
2166
|
+
if (_chunk3R3QVKY5cjs.soundsDominantSeventh.call(void 0, chord)) {
|
|
2167
2167
|
score += DOMINANT_CREDIT;
|
|
2168
2168
|
} else if (chord.quality === "maj") {
|
|
2169
2169
|
score += DOMINANT_CREDIT * 0.5;
|
|
@@ -2175,17 +2175,17 @@ function chordFitsKey(chord, candidate) {
|
|
|
2175
2175
|
return score;
|
|
2176
2176
|
}
|
|
2177
2177
|
function detectModulations(chords, opts = {}) {
|
|
2178
|
-
|
|
2178
|
+
_chunkS5BKZZGMcjs.assertArray.call(void 0, chords, "modulation chord segments");
|
|
2179
2179
|
chords.forEach((segment, index) => {
|
|
2180
|
-
|
|
2180
|
+
_chunkS5BKZZGMcjs.assertRecord.call(void 0, segment, `modulation chord segments[${index}]`);
|
|
2181
2181
|
});
|
|
2182
|
-
const meters =
|
|
2183
|
-
const bar =
|
|
2182
|
+
const meters = _chunkS5BKZZGMcjs.resolveMeters.call(void 0, opts, "modulation meters");
|
|
2183
|
+
const bar = _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, 0, meters);
|
|
2184
2184
|
const expectedKeyBeats = _nullishCoalesce(opts.expectedKeyBeats, () => ( bar * 4));
|
|
2185
|
-
|
|
2185
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, expectedKeyBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "expectedKeyBeats");
|
|
2186
2186
|
const minKeyBeats = _nullishCoalesce(opts.minKeyBeats, () => ( bar));
|
|
2187
|
-
|
|
2188
|
-
|
|
2187
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, minKeyBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "minKeyBeats");
|
|
2188
|
+
_chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0,
|
|
2189
2189
|
chords.length * KEY_CANDIDATES.length,
|
|
2190
2190
|
"modulation chord segments",
|
|
2191
2191
|
opts.budget
|
|
@@ -2193,7 +2193,7 @@ function detectModulations(chords, opts = {}) {
|
|
|
2193
2193
|
const sorted = [...chords].filter((segment) => segment.endBeat > segment.startBeat).sort((a, b) => a.startBeat - b.startBeat);
|
|
2194
2194
|
const lastChordEnd = sorted.reduce((end, segment) => Math.max(end, segment.endBeat), 0);
|
|
2195
2195
|
const totalBeats = _nullishCoalesce(opts.totalBeats, () => ( lastChordEnd));
|
|
2196
|
-
|
|
2196
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, totalBeats, 0, Number.MAX_SAFE_INTEGER, "modulation totalBeats");
|
|
2197
2197
|
const ordered = sorted.map((segment) => ({ ...segment, endBeat: Math.min(segment.endBeat, totalBeats) })).filter((segment) => segment.endBeat > segment.startBeat);
|
|
2198
2198
|
if (ordered.length === 0) {
|
|
2199
2199
|
return [];
|
|
@@ -2216,14 +2216,14 @@ function detectModulations(chords, opts = {}) {
|
|
|
2216
2216
|
if (arriving === void 0 || approaching === void 0 || slot === void 0) {
|
|
2217
2217
|
continue;
|
|
2218
2218
|
}
|
|
2219
|
-
const isDominantMotion =
|
|
2219
|
+
const isDominantMotion = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, approaching.rootPc - arriving.rootPc) === 7 && _chunk3R3QVKY5cjs.soundsDominantSeventh.call(void 0, approaching);
|
|
2220
2220
|
if (!isDominantMotion) {
|
|
2221
2221
|
continue;
|
|
2222
2222
|
}
|
|
2223
2223
|
const length = slot.endBeat - slot.startBeat;
|
|
2224
2224
|
for (let c = 0; c < KEY_CANDIDATES.length; c += 1) {
|
|
2225
2225
|
const candidate = KEY_CANDIDATES[c];
|
|
2226
|
-
if (candidate !== void 0 &&
|
|
2226
|
+
if (candidate !== void 0 && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, arriving.rootPc - candidate.rootPc) === 0) {
|
|
2227
2227
|
slot.scores[c] = (_nullishCoalesce(slot.scores[c], () => ( 0))) + CADENCE_CREDIT * length;
|
|
2228
2228
|
}
|
|
2229
2229
|
}
|
|
@@ -2237,7 +2237,7 @@ function detectModulations(chords, opts = {}) {
|
|
|
2237
2237
|
const profile = resolveKeyProfile(opts.profile);
|
|
2238
2238
|
const regions = grouped.map((region) => {
|
|
2239
2239
|
const candidate = KEY_CANDIDATES[region.candidate];
|
|
2240
|
-
const key =
|
|
2240
|
+
const key = _chunk3R3QVKY5cjs.resolveKey.call(void 0, _nullishCoalesce(_optionalChain([candidate, 'optionalAccess', _31 => _31.key]), () => ( _chunk3R3QVKY5cjs.majorKey.call(void 0, 0))));
|
|
2241
2241
|
const weights = new Array(PITCH_CLASSES).fill(0);
|
|
2242
2242
|
for (let i = region.from; i < region.toExclusive; i += 1) {
|
|
2243
2243
|
const segment = ordered[i];
|
|
@@ -2245,10 +2245,10 @@ function detectModulations(chords, opts = {}) {
|
|
|
2245
2245
|
continue;
|
|
2246
2246
|
}
|
|
2247
2247
|
const overlap = segment.endBeat - segment.startBeat;
|
|
2248
|
-
if (overlap <=
|
|
2248
|
+
if (overlap <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2249
2249
|
continue;
|
|
2250
2250
|
}
|
|
2251
|
-
for (const pc of
|
|
2251
|
+
for (const pc of _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, segment.chord)) {
|
|
2252
2252
|
weights[pc] = (_nullishCoalesce(weights[pc], () => ( 0))) + overlap;
|
|
2253
2253
|
}
|
|
2254
2254
|
}
|
|
@@ -2273,7 +2273,7 @@ function detectModulations(chords, opts = {}) {
|
|
|
2273
2273
|
var THIRD_SEMITONES = [3, 4];
|
|
2274
2274
|
var FIFTH_SEMITONES = [6, 7, 8];
|
|
2275
2275
|
function triadCore(chord) {
|
|
2276
|
-
const root =
|
|
2276
|
+
const root = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc);
|
|
2277
2277
|
let third;
|
|
2278
2278
|
let fifth;
|
|
2279
2279
|
for (const interval of chord.intervals) {
|
|
@@ -2289,7 +2289,7 @@ function triadCore(chord) {
|
|
|
2289
2289
|
if (third === void 0 || fifth === void 0) {
|
|
2290
2290
|
return null;
|
|
2291
2291
|
}
|
|
2292
|
-
return [root,
|
|
2292
|
+
return [root, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, root + third), _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, root + fifth)].sort((a, b) => a - b);
|
|
2293
2293
|
}
|
|
2294
2294
|
function lastChordFinishedBy(chords) {
|
|
2295
2295
|
const byEnd = chords.map((_, index) => index).sort((a, b) => (_nullishCoalesce(_optionalChain([chords, 'access', _34 => _34[a], 'optionalAccess', _35 => _35.endBeat]), () => ( 0))) - (_nullishCoalesce(_optionalChain([chords, 'access', _36 => _36[b], 'optionalAccess', _37 => _37.endBeat]), () => ( 0))));
|
|
@@ -2327,7 +2327,7 @@ function attachPivots(regions, chords) {
|
|
|
2327
2327
|
if (previous === void 0 || current === void 0) {
|
|
2328
2328
|
continue;
|
|
2329
2329
|
}
|
|
2330
|
-
const last = finished(current.startBeat +
|
|
2330
|
+
const last = finished(current.startBeat + _chunkS5BKZZGMcjs.BEAT_EPS);
|
|
2331
2331
|
if (last === void 0) {
|
|
2332
2332
|
continue;
|
|
2333
2333
|
}
|
|
@@ -2335,9 +2335,9 @@ function attachPivots(regions, chords) {
|
|
|
2335
2335
|
if (core === null) {
|
|
2336
2336
|
continue;
|
|
2337
2337
|
}
|
|
2338
|
-
const root =
|
|
2338
|
+
const root = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, last.chord.rootPc);
|
|
2339
2339
|
const pivot = pivotChords(previous.key, current.key).find(
|
|
2340
|
-
(entry) => entry.chord.rootPc === root && sameTones(
|
|
2340
|
+
(entry) => entry.chord.rootPc === root && sameTones(_chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, entry.chord), core)
|
|
2341
2341
|
);
|
|
2342
2342
|
if (pivot !== void 0) {
|
|
2343
2343
|
current.pivot = pivot;
|
|
@@ -2362,12 +2362,12 @@ function keyLookup(regions, fallback) {
|
|
|
2362
2362
|
};
|
|
2363
2363
|
}
|
|
2364
2364
|
function prevailingKeyOf(regions) {
|
|
2365
|
-
|
|
2365
|
+
_chunkS5BKZZGMcjs.assertArray.call(void 0, regions, "key regions");
|
|
2366
2366
|
const totals = /* @__PURE__ */ new Map();
|
|
2367
2367
|
for (const [index, given] of regions.entries()) {
|
|
2368
|
-
const region =
|
|
2369
|
-
|
|
2370
|
-
const id = `${
|
|
2368
|
+
const region = _chunkS5BKZZGMcjs.assertRecord.call(void 0, given, `key regions[${index}]`);
|
|
2369
|
+
_chunkS5BKZZGMcjs.assertRecord.call(void 0, region.key, `key regions[${index}].key`);
|
|
2370
|
+
const id = `${_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, region.key.scale.rootPc)}:${region.key.scale.modeMask12}`;
|
|
2371
2371
|
const entry = totals.get(id);
|
|
2372
2372
|
const length = Math.max(0, region.endBeat - region.startBeat);
|
|
2373
2373
|
if (entry === void 0) {
|
|
@@ -2392,11 +2392,11 @@ function keyScaleAt(key) {
|
|
|
2392
2392
|
if (typeof key === "function") {
|
|
2393
2393
|
return key;
|
|
2394
2394
|
}
|
|
2395
|
-
const scale =
|
|
2395
|
+
const scale = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key);
|
|
2396
2396
|
return () => scale;
|
|
2397
2397
|
}
|
|
2398
2398
|
function toVoiceNotes(events) {
|
|
2399
|
-
|
|
2399
|
+
_chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, events, "voice notes", { allowNonPositiveDuration: true });
|
|
2400
2400
|
return events.map((event, index) => ({ ...event, id: index, originalIndex: index }));
|
|
2401
2401
|
}
|
|
2402
2402
|
function intervalAboveBass(pitch, others, chord) {
|
|
@@ -2408,7 +2408,7 @@ function intervalAboveBass(pitch, others, chord) {
|
|
|
2408
2408
|
return ((pitch - bass) % 12 + 12) % 12;
|
|
2409
2409
|
}
|
|
2410
2410
|
const ref = _nullishCoalesce(chord.bassPc, () => ( chord.rootPc));
|
|
2411
|
-
return ((
|
|
2411
|
+
return ((_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, pitch) - _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, ref)) % 12 + 12) % 12;
|
|
2412
2412
|
}
|
|
2413
2413
|
var TENSION_DEGREE_BY_INTERVAL = {
|
|
2414
2414
|
1: 9,
|
|
@@ -2427,7 +2427,7 @@ function asSounded(chord) {
|
|
|
2427
2427
|
if (chord.bassPc === void 0) {
|
|
2428
2428
|
return chord;
|
|
2429
2429
|
}
|
|
2430
|
-
return { ...chord, intervals: [...chord.intervals,
|
|
2430
|
+
return { ...chord, intervals: [...chord.intervals, _chunk3R3QVKY5cjs.intervalAboveRoot.call(void 0, chord.bassPc, chord)] };
|
|
2431
2431
|
}
|
|
2432
2432
|
function isStep(a, b) {
|
|
2433
2433
|
const d = Math.abs(a - b);
|
|
@@ -2456,19 +2456,19 @@ var STEP_RESOLUTION = 2;
|
|
|
2456
2456
|
var NEAREST_CHORD_TONE_REACH = 12;
|
|
2457
2457
|
function nearestChordTone(pitch, chord, maxDistance) {
|
|
2458
2458
|
for (let delta = 1; delta <= maxDistance; delta += 1) {
|
|
2459
|
-
if (
|
|
2459
|
+
if (_chunk3R3QVKY5cjs.isChordMember.call(void 0, pitch - delta, chord)) {
|
|
2460
2460
|
return pitch - delta;
|
|
2461
2461
|
}
|
|
2462
|
-
if (
|
|
2462
|
+
if (_chunk3R3QVKY5cjs.isChordMember.call(void 0, pitch + delta, chord)) {
|
|
2463
2463
|
return pitch + delta;
|
|
2464
2464
|
}
|
|
2465
2465
|
}
|
|
2466
2466
|
return void 0;
|
|
2467
2467
|
}
|
|
2468
2468
|
function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2469
|
+
_chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, voice, "voice notes", { allowNonPositiveDuration: true });
|
|
2470
|
+
_chunkS5BKZZGMcjs.assertFunction.call(void 0, chordAtBeat2, "chordAtBeat");
|
|
2471
|
+
_chunkS5BKZZGMcjs.assertFunction.call(void 0, otherVoicesAtBeat, "otherVoicesAtBeat");
|
|
2472
2472
|
const keyAt = keyScaleAt(key);
|
|
2473
2473
|
const result = [];
|
|
2474
2474
|
for (let i = 0; i < voice.length; i += 1) {
|
|
@@ -2484,11 +2484,11 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2484
2484
|
const next = nextNote !== void 0 && adjacent(noteEnd, nextNote.startBeat) ? nextNote : void 0;
|
|
2485
2485
|
const chord = chordAtBeat2(note.startBeat);
|
|
2486
2486
|
const labels = [];
|
|
2487
|
-
const member =
|
|
2487
|
+
const member = _chunk3R3QVKY5cjs.isChordMember.call(void 0, note.pitch, chord);
|
|
2488
2488
|
let handled = false;
|
|
2489
2489
|
if (chord && member) {
|
|
2490
|
-
const role =
|
|
2491
|
-
const degree = role === null ? tensionDegree(
|
|
2490
|
+
const role = _chunk3R3QVKY5cjs.chordToneRole.call(void 0, note.pitch, chord);
|
|
2491
|
+
const degree = role === null ? tensionDegree(_chunk3R3QVKY5cjs.intervalAboveRoot.call(void 0, note.pitch, chord)) : void 0;
|
|
2492
2492
|
if (role) {
|
|
2493
2493
|
labels.push({ kind: "chordTone", role });
|
|
2494
2494
|
handled = true;
|
|
@@ -2496,7 +2496,7 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2496
2496
|
labels.push({ kind: "tension", degree });
|
|
2497
2497
|
handled = true;
|
|
2498
2498
|
} else {
|
|
2499
|
-
const bassRole =
|
|
2499
|
+
const bassRole = _chunk3R3QVKY5cjs.chordToneRole.call(void 0, note.pitch, asSounded(chord));
|
|
2500
2500
|
if (bassRole !== null) {
|
|
2501
2501
|
labels.push({ kind: "chordTone", role: bassRole });
|
|
2502
2502
|
handled = true;
|
|
@@ -2505,11 +2505,11 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2505
2505
|
}
|
|
2506
2506
|
if (!handled && chord && prev && next) {
|
|
2507
2507
|
const prevChord = chordAtBeat2(prev.startBeat);
|
|
2508
|
-
const prepared = prev.pitch === note.pitch &&
|
|
2508
|
+
const prepared = prev.pitch === note.pitch && _chunk3R3QVKY5cjs.isChordMember.call(void 0, prev.pitch, prevChord);
|
|
2509
2509
|
const resolves = isStep(next.pitch, note.pitch);
|
|
2510
2510
|
const others = otherVoicesAtBeat(note.startBeat);
|
|
2511
2511
|
const verticallyDissonant = others.some(
|
|
2512
|
-
(ov) =>
|
|
2512
|
+
(ov) => _chunk3R3QVKY5cjs.createsVerticalDissonance.call(void 0, note.pitch, ov.pitch, true)
|
|
2513
2513
|
);
|
|
2514
2514
|
if (prepared && verticallyDissonant && resolves) {
|
|
2515
2515
|
const ic = intervalAboveBass(note.pitch, others, chord);
|
|
@@ -2521,8 +2521,8 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2521
2521
|
}
|
|
2522
2522
|
}
|
|
2523
2523
|
if (!handled && chord && prev && next) {
|
|
2524
|
-
const prevMember =
|
|
2525
|
-
const nextMember =
|
|
2524
|
+
const prevMember = _chunk3R3QVKY5cjs.isChordMember.call(void 0, prev.pitch, chordAtBeat2(prev.startBeat));
|
|
2525
|
+
const nextMember = _chunk3R3QVKY5cjs.isChordMember.call(void 0, next.pitch, chordAtBeat2(next.startBeat));
|
|
2526
2526
|
const up = note.pitch - prev.pitch > 0;
|
|
2527
2527
|
const contInto = next.pitch - note.pitch > 0;
|
|
2528
2528
|
const sameDir = note.pitch !== prev.pitch && next.pitch !== note.pitch && up === contInto;
|
|
@@ -2531,20 +2531,20 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2531
2531
|
handled = true;
|
|
2532
2532
|
}
|
|
2533
2533
|
}
|
|
2534
|
-
if (!handled && chord && prev && next && !member && prev.pitch === next.pitch &&
|
|
2534
|
+
if (!handled && chord && prev && next && !member && prev.pitch === next.pitch && _chunk3R3QVKY5cjs.isChordMember.call(void 0, prev.pitch, chordAtBeat2(prev.startBeat)) && isStep(note.pitch, prev.pitch)) {
|
|
2535
2535
|
labels.push({ kind: "neighbor" });
|
|
2536
2536
|
handled = true;
|
|
2537
2537
|
}
|
|
2538
2538
|
if (!handled && chord && next && !member && note.pitch === next.pitch) {
|
|
2539
2539
|
const nextChord = chordAtBeat2(next.startBeat);
|
|
2540
|
-
if (
|
|
2540
|
+
if (_chunk3R3QVKY5cjs.isChordMember.call(void 0, next.pitch, nextChord)) {
|
|
2541
2541
|
labels.push({ kind: "anticipation" });
|
|
2542
2542
|
handled = true;
|
|
2543
2543
|
}
|
|
2544
2544
|
}
|
|
2545
2545
|
if (!handled && chord && prev && next && !member) {
|
|
2546
|
-
const prevMember =
|
|
2547
|
-
const nextMember =
|
|
2546
|
+
const prevMember = _chunk3R3QVKY5cjs.isChordMember.call(void 0, prev.pitch, chordAtBeat2(prev.startBeat));
|
|
2547
|
+
const nextMember = _chunk3R3QVKY5cjs.isChordMember.call(void 0, next.pitch, chordAtBeat2(next.startBeat));
|
|
2548
2548
|
const leapFromPrev = Math.abs(note.pitch - prev.pitch) >= LEAP_SEMITONES;
|
|
2549
2549
|
const stepToNext = isStep(next.pitch, note.pitch);
|
|
2550
2550
|
const opposite = note.pitch - prev.pitch > 0 !== next.pitch - note.pitch > 0;
|
|
@@ -2554,8 +2554,8 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2554
2554
|
}
|
|
2555
2555
|
}
|
|
2556
2556
|
if (!handled && chord && prev && next && !member) {
|
|
2557
|
-
const prevMember =
|
|
2558
|
-
const nextMember =
|
|
2557
|
+
const prevMember = _chunk3R3QVKY5cjs.isChordMember.call(void 0, prev.pitch, chordAtBeat2(prev.startBeat));
|
|
2558
|
+
const nextMember = _chunk3R3QVKY5cjs.isChordMember.call(void 0, next.pitch, chordAtBeat2(next.startBeat));
|
|
2559
2559
|
const stepFromPrev = isStep(note.pitch, prev.pitch);
|
|
2560
2560
|
const leapToNext = Math.abs(next.pitch - note.pitch) >= LEAP_SEMITONES;
|
|
2561
2561
|
const opposite = note.pitch - prev.pitch > 0 !== next.pitch - note.pitch > 0;
|
|
@@ -2565,7 +2565,7 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2565
2565
|
}
|
|
2566
2566
|
}
|
|
2567
2567
|
if (!handled && chord && !member) {
|
|
2568
|
-
const ic =
|
|
2568
|
+
const ic = _chunk3R3QVKY5cjs.intervalAboveRoot.call(void 0, note.pitch, chord);
|
|
2569
2569
|
const degree = tensionDegree(ic);
|
|
2570
2570
|
const colours = NATURAL_TENSION_INTERVALS.has(ic) || chord.intervals.some((i2) => i2 === 10 || i2 === 11);
|
|
2571
2571
|
const avoid = ic === 5 && chord.intervals.includes(4) && !chord.intervals.includes(5) || ic === 11 && chord.intervals.includes(4) && chord.intervals.includes(10);
|
|
@@ -2584,7 +2584,7 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2584
2584
|
);
|
|
2585
2585
|
}
|
|
2586
2586
|
}
|
|
2587
|
-
if (next &&
|
|
2587
|
+
if (next && _chunk3R3QVKY5cjs.isLeadingToneResolution.call(void 0, note.pitch, next.pitch, keyAt(next.startBeat))) {
|
|
2588
2588
|
labels.push({ kind: "leadingTone", resolveTo: next.pitch });
|
|
2589
2589
|
}
|
|
2590
2590
|
const analyzed = {
|
|
@@ -2635,22 +2635,22 @@ function describe(labels) {
|
|
|
2635
2635
|
|
|
2636
2636
|
// src/analyze/timeline/index.ts
|
|
2637
2637
|
function assertChordTimeline(timeline, name = "timeline") {
|
|
2638
|
-
const read =
|
|
2639
|
-
|
|
2640
|
-
const segments =
|
|
2638
|
+
const read = _chunkS5BKZZGMcjs.assertRecord.call(void 0, timeline, name);
|
|
2639
|
+
_chunkS5BKZZGMcjs.assertFunction.call(void 0, read.at, `${name}.at`);
|
|
2640
|
+
const segments = _chunkS5BKZZGMcjs.assertArray.call(void 0, read.segments, `${name}.segments`);
|
|
2641
2641
|
for (let index = 0; index < segments.length; index += 1) {
|
|
2642
|
-
const segment =
|
|
2643
|
-
|
|
2644
|
-
|
|
2642
|
+
const segment = _chunkS5BKZZGMcjs.assertRecord.call(void 0, segments[index], `${name}.segments[${index}]`);
|
|
2643
|
+
_chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, segment.startBeat, `${name}.segments[${index}].startBeat`);
|
|
2644
|
+
_chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, segment.endBeat, `${name}.segments[${index}].endBeat`);
|
|
2645
2645
|
}
|
|
2646
2646
|
return read;
|
|
2647
2647
|
}
|
|
2648
2648
|
function chordTimelineFromChords(chords, totalBeats) {
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2649
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, totalBeats, 0, Number.MAX_SAFE_INTEGER, "timeline totalBeats");
|
|
2650
|
+
_chunkS5BKZZGMcjs.assertArray.call(void 0, chords, "chords");
|
|
2651
|
+
_chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, chords.length, "timeline chords");
|
|
2652
2652
|
for (let index = 0; index < chords.length; index += 1) {
|
|
2653
|
-
|
|
2653
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0,
|
|
2654
2654
|
_nullishCoalesce(_optionalChain([chords, 'access', _42 => _42[index], 'optionalAccess', _43 => _43.startBeat]), () => ( Number.NaN)),
|
|
2655
2655
|
-Number.MAX_SAFE_INTEGER,
|
|
2656
2656
|
Number.MAX_SAFE_INTEGER,
|
|
@@ -2665,13 +2665,13 @@ function chordTimelineFromChords(chords, totalBeats) {
|
|
|
2665
2665
|
return {
|
|
2666
2666
|
startBeat: gc.startBeat,
|
|
2667
2667
|
endBeat,
|
|
2668
|
-
chord:
|
|
2668
|
+
chord: _chunk3R3QVKY5cjs.chordFromSpan.call(void 0, gc)
|
|
2669
2669
|
};
|
|
2670
2670
|
}).filter((seg) => seg.endBeat > seg.startBeat);
|
|
2671
2671
|
return { at: segmentLookup(segments), segments };
|
|
2672
2672
|
}
|
|
2673
2673
|
function chordAtBeat(segments, beat) {
|
|
2674
|
-
|
|
2674
|
+
_chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, beat, "timeline query beat");
|
|
2675
2675
|
const candidate = segments[firstAfter(segments, beat) - 1];
|
|
2676
2676
|
return candidate !== void 0 && beat >= candidate.startBeat && beat < candidate.endBeat ? candidate.chord : null;
|
|
2677
2677
|
}
|
|
@@ -2691,7 +2691,7 @@ function firstAfter(segments, beat) {
|
|
|
2691
2691
|
function segmentStartingAt(segments, beat) {
|
|
2692
2692
|
const index = firstAfter(segments, beat);
|
|
2693
2693
|
for (const candidate of [segments[index - 1], segments[index]]) {
|
|
2694
|
-
if (candidate !== void 0 && Math.abs(candidate.startBeat - beat) <
|
|
2694
|
+
if (candidate !== void 0 && Math.abs(candidate.startBeat - beat) < _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2695
2695
|
return candidate;
|
|
2696
2696
|
}
|
|
2697
2697
|
}
|
|
@@ -2712,10 +2712,10 @@ var OCTAVE = 12;
|
|
|
2712
2712
|
function scoreMatch(match, weights, maxWeight, key, pedalPc) {
|
|
2713
2713
|
const rootWeight = maxWeight > 0 ? (_nullishCoalesce(weights[match.rootPc], () => ( 0))) / maxWeight : 0;
|
|
2714
2714
|
const rootStanding = match.inversion === 0 ? Math.max(rootWeight, BASS_ROOT_STANDING) : rootWeight;
|
|
2715
|
-
const chord =
|
|
2715
|
+
const chord = _chunk3R3QVKY5cjs.makeChord.call(void 0, match.rootPc, match.quality);
|
|
2716
2716
|
const account = matchAccount(match, chord, pedalPc);
|
|
2717
2717
|
let score = rootStanding;
|
|
2718
|
-
if (
|
|
2718
|
+
if (_chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord).every((pc) => _chunk3R3QVKY5cjs.isScaleTone.call(void 0, pc, key))) {
|
|
2719
2719
|
score += DIATONIC_BONUS;
|
|
2720
2720
|
}
|
|
2721
2721
|
if (account.exact) {
|
|
@@ -2730,7 +2730,7 @@ function isSlashReading(match, pedalPc) {
|
|
|
2730
2730
|
return pedalPc !== null && match.inversion === null && match.missingPcs.length === 0 && match.extraPcs.length === 1 && match.extraPcs[0] === pedalPc && SLASH_UPPER_QUALITIES.has(match.quality);
|
|
2731
2731
|
}
|
|
2732
2732
|
function namesAsExtension(chord, pc) {
|
|
2733
|
-
return chord.intervals.some((iv) => iv >= OCTAVE &&
|
|
2733
|
+
return chord.intervals.some((iv) => iv >= OCTAVE && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc + iv) === pc);
|
|
2734
2734
|
}
|
|
2735
2735
|
function matchAccount(match, chord, pedalPc) {
|
|
2736
2736
|
const unvoiced = pedalPc !== null && namesAsExtension(chord, pedalPc) ? 1 : 0;
|
|
@@ -2746,10 +2746,10 @@ function bassSoundsOnlyBelow(notes, windowStart, windowEnd, bassPc) {
|
|
|
2746
2746
|
let highestBass = Number.NEGATIVE_INFINITY;
|
|
2747
2747
|
for (const note of notes) {
|
|
2748
2748
|
const overlap = Math.min(note.startBeat + note.durationBeat, windowEnd) - Math.max(note.startBeat, windowStart);
|
|
2749
|
-
if (overlap <=
|
|
2749
|
+
if (overlap <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2750
2750
|
continue;
|
|
2751
2751
|
}
|
|
2752
|
-
if (
|
|
2752
|
+
if (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, note.pitch) === bassPc) {
|
|
2753
2753
|
highestBass = Math.max(highestBass, note.pitch);
|
|
2754
2754
|
} else {
|
|
2755
2755
|
upperFloor = Math.min(upperFloor, note.pitch);
|
|
@@ -2758,7 +2758,7 @@ function bassSoundsOnlyBelow(notes, windowStart, windowEnd, bassPc) {
|
|
|
2758
2758
|
return highestBass <= upperFloor;
|
|
2759
2759
|
}
|
|
2760
2760
|
function chordConfidence(chord, weights, totalWeight, exact) {
|
|
2761
|
-
const tones = new Set(
|
|
2761
|
+
const tones = new Set(_chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord));
|
|
2762
2762
|
let chordWeight = 0;
|
|
2763
2763
|
for (let pc = 0; pc < 12; pc += 1) {
|
|
2764
2764
|
if (tones.has(pc)) {
|
|
@@ -2776,12 +2776,12 @@ function analyzeWindow(notes, windowStart, windowEnd, meters, key) {
|
|
|
2776
2776
|
windowEnd,
|
|
2777
2777
|
meters
|
|
2778
2778
|
);
|
|
2779
|
-
if (totalWeight <=
|
|
2779
|
+
if (totalWeight <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2780
2780
|
return null;
|
|
2781
2781
|
}
|
|
2782
2782
|
const ranked = weights.map((weight, pc) => ({ pc, weight })).filter(({ weight }) => weight > 0).sort((a, b) => b.weight - a.weight || a.pc - b.pc);
|
|
2783
2783
|
const selected = ranked.filter(({ weight }) => weight >= maxWeight * NOISE_THRESHOLD_RATIO).slice(0, MAX_DETECTION_PCS).map(({ pc }) => pc);
|
|
2784
|
-
const bassPc =
|
|
2784
|
+
const bassPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, lowestPitch);
|
|
2785
2785
|
const hasBass = selected.includes(bassPc);
|
|
2786
2786
|
const detectionPitches = hasBass ? selected.map((pc) => pc === bassPc ? pc : pc + 12) : selected;
|
|
2787
2787
|
const pedalPc = hasBass && bassSoundsOnlyBelow(notes, windowStart, windowEnd, bassPc) ? bassPc : null;
|
|
@@ -2789,17 +2789,17 @@ function analyzeWindow(notes, windowStart, windowEnd, meters, key) {
|
|
|
2789
2789
|
let bestMatch = null;
|
|
2790
2790
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
2791
2791
|
for (const match of matches) {
|
|
2792
|
-
const score = scoreMatch(match, weights, maxWeight,
|
|
2792
|
+
const score = scoreMatch(match, weights, maxWeight, _chunk3R3QVKY5cjs.scaleOf.call(void 0, key), pedalPc);
|
|
2793
2793
|
if (score > bestScore) {
|
|
2794
2794
|
bestScore = score;
|
|
2795
2795
|
bestMatch = match;
|
|
2796
2796
|
}
|
|
2797
2797
|
}
|
|
2798
2798
|
if (bestMatch) {
|
|
2799
|
-
const chord =
|
|
2799
|
+
const chord = _chunk3R3QVKY5cjs.makeChord.call(void 0, bestMatch.rootPc, bestMatch.quality, bestMatch.bassPc);
|
|
2800
2800
|
const account = matchAccount(
|
|
2801
2801
|
bestMatch,
|
|
2802
|
-
|
|
2802
|
+
_chunk3R3QVKY5cjs.makeChord.call(void 0, bestMatch.rootPc, bestMatch.quality),
|
|
2803
2803
|
pedalPc
|
|
2804
2804
|
);
|
|
2805
2805
|
const reading = {
|
|
@@ -2823,7 +2823,7 @@ function shared(chord) {
|
|
|
2823
2823
|
}
|
|
2824
2824
|
var DOMINANT_ABOVE_TONIC = 7;
|
|
2825
2825
|
function resolvesOntoDominant(readings, index, key) {
|
|
2826
|
-
const dominantPc =
|
|
2826
|
+
const dominantPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc + DOMINANT_ABOVE_TONIC);
|
|
2827
2827
|
const candidate = _optionalChain([readings, 'access', _46 => _46[index], 'optionalAccess', _47 => _47.chord]);
|
|
2828
2828
|
for (let i = index + 1; i < readings.length; i += 1) {
|
|
2829
2829
|
const next = readings[i];
|
|
@@ -2834,10 +2834,10 @@ function resolvesOntoDominant(readings, index, key) {
|
|
|
2834
2834
|
if (candidate !== void 0 && sameChord(chord, candidate)) {
|
|
2835
2835
|
continue;
|
|
2836
2836
|
}
|
|
2837
|
-
if (
|
|
2837
|
+
if (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, _nullishCoalesce(chord.bassPc, () => ( chord.rootPc))) !== dominantPc) {
|
|
2838
2838
|
return false;
|
|
2839
2839
|
}
|
|
2840
|
-
if (
|
|
2840
|
+
if (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc) === dominantPc) {
|
|
2841
2841
|
return true;
|
|
2842
2842
|
}
|
|
2843
2843
|
}
|
|
@@ -2870,7 +2870,7 @@ var LEXICON_TONES = (() => {
|
|
|
2870
2870
|
for (const quality of SEGMENTATION_QUALITIES) {
|
|
2871
2871
|
LEXICON_ROOTS[candidate] = rootPc;
|
|
2872
2872
|
LEXICON_TONE_START[candidate] = tones.length;
|
|
2873
|
-
tones.push(...
|
|
2873
|
+
tones.push(..._chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, _chunk3R3QVKY5cjs.makeChord.call(void 0, rootPc, quality)));
|
|
2874
2874
|
candidate += 1;
|
|
2875
2875
|
}
|
|
2876
2876
|
}
|
|
@@ -2891,7 +2891,7 @@ function candidateScore(candidate, weights, totalWeight) {
|
|
|
2891
2891
|
for (let index = first; index < last; index += 1) {
|
|
2892
2892
|
const weight = _nullishCoalesce(weights[_nullishCoalesce(LEXICON_TONES[index], () => ( 0))], () => ( 0));
|
|
2893
2893
|
covered += weight;
|
|
2894
|
-
if (weight <=
|
|
2894
|
+
if (weight <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2895
2895
|
missing += 1;
|
|
2896
2896
|
}
|
|
2897
2897
|
}
|
|
@@ -2907,16 +2907,16 @@ function slotOfBeat(grid, beat) {
|
|
|
2907
2907
|
}
|
|
2908
2908
|
function createBoundaryTables(slotCount, budget) {
|
|
2909
2909
|
return {
|
|
2910
|
-
scores:
|
|
2911
|
-
back:
|
|
2912
|
-
costs:
|
|
2913
|
-
spare:
|
|
2914
|
-
path:
|
|
2910
|
+
scores: _chunkS5BKZZGMcjs.allocateCandidateTable.call(void 0, slotCount, LEXICON_SIZE, "timeline window scores", budget),
|
|
2911
|
+
back: _chunkS5BKZZGMcjs.allocateChoiceTable.call(void 0, slotCount, LEXICON_SIZE, "timeline window choices", budget),
|
|
2912
|
+
costs: _chunkS5BKZZGMcjs.allocateCandidateTable.call(void 0, 1, LEXICON_SIZE, "timeline window costs", budget),
|
|
2913
|
+
spare: _chunkS5BKZZGMcjs.allocateCandidateTable.call(void 0, 1, LEXICON_SIZE, "timeline window costs", budget),
|
|
2914
|
+
path: _chunkS5BKZZGMcjs.allocateChoiceTable.call(void 0, slotCount, 1, "timeline window path", budget)
|
|
2915
2915
|
};
|
|
2916
2916
|
}
|
|
2917
2917
|
function scoreSlot(tables, slot, index) {
|
|
2918
2918
|
const base = index * LEXICON_SIZE;
|
|
2919
|
-
if (slot.totalWeight <=
|
|
2919
|
+
if (slot.totalWeight <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2920
2920
|
tables.scores.fill(0, base, base + LEXICON_SIZE);
|
|
2921
2921
|
return;
|
|
2922
2922
|
}
|
|
@@ -2946,7 +2946,7 @@ function chooseBoundaries(tables, from, to, grid, meters, changeCost) {
|
|
|
2946
2946
|
}
|
|
2947
2947
|
}
|
|
2948
2948
|
const slotStart = beatOfSlot(grid, from + i);
|
|
2949
|
-
const accent =
|
|
2949
|
+
const accent = _chunkS5BKZZGMcjs.metricWeight.call(void 0, slotStart, meters);
|
|
2950
2950
|
const penalty = changeCost * (1 - STRONG_BEAT_DISCOUNT2 * accent / MAX_METRIC_WEIGHT2);
|
|
2951
2951
|
const rowBase = (from + i) * LEXICON_SIZE;
|
|
2952
2952
|
const change = cheapest + penalty;
|
|
@@ -2988,7 +2988,7 @@ function chooseBoundaries(tables, from, to, grid, meters, changeCost) {
|
|
|
2988
2988
|
}
|
|
2989
2989
|
function slotBeatsWithin(gridUnit, minChordBeats, harmonicRhythm) {
|
|
2990
2990
|
const resolution = Math.min(minChordBeats, harmonicRhythm);
|
|
2991
|
-
const divisions = Math.max(1, Math.ceil(gridUnit / resolution -
|
|
2991
|
+
const divisions = Math.max(1, Math.ceil(gridUnit / resolution - _chunkS5BKZZGMcjs.BEAT_EPS));
|
|
2992
2992
|
return gridUnit / divisions;
|
|
2993
2993
|
}
|
|
2994
2994
|
function gridSpans(slotCount, grid) {
|
|
@@ -3004,7 +3004,7 @@ function dynamicSpans(slotWeights, tables, grid, harmonicRhythm, meters) {
|
|
|
3004
3004
|
let weightSum = 0;
|
|
3005
3005
|
for (let i = 0; i < slotCount; i += 1) {
|
|
3006
3006
|
const weight = _nullishCoalesce(_optionalChain([slotWeights, 'access', _48 => _48[i], 'optionalAccess', _49 => _49.totalWeight]), () => ( 0));
|
|
3007
|
-
if (weight >
|
|
3007
|
+
if (weight > _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
3008
3008
|
soundingSlots += 1;
|
|
3009
3009
|
weightSum += weight;
|
|
3010
3010
|
}
|
|
@@ -3014,7 +3014,7 @@ function dynamicSpans(slotWeights, tables, grid, harmonicRhythm, meters) {
|
|
|
3014
3014
|
}
|
|
3015
3015
|
const meanSlotWeight = weightSum / soundingSlots;
|
|
3016
3016
|
const changeCost = CHANGE_COST * meanSlotWeight * (harmonicRhythm / slotBeats);
|
|
3017
|
-
const silent = slotWeights.map((slot) => slot.totalWeight <=
|
|
3017
|
+
const silent = slotWeights.map((slot) => slot.totalWeight <= _chunkS5BKZZGMcjs.BEAT_EPS);
|
|
3018
3018
|
const breaks = new Array(slotCount).fill(false);
|
|
3019
3019
|
for (let i = 0; i < slotCount; ) {
|
|
3020
3020
|
if (!silent[i]) {
|
|
@@ -3025,7 +3025,7 @@ function dynamicSpans(slotWeights, tables, grid, harmonicRhythm, meters) {
|
|
|
3025
3025
|
while (end < slotCount && silent[end]) {
|
|
3026
3026
|
end += 1;
|
|
3027
3027
|
}
|
|
3028
|
-
if ((end - i) * slotBeats >= harmonicRhythm -
|
|
3028
|
+
if ((end - i) * slotBeats >= harmonicRhythm - _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
3029
3029
|
for (let k = i; k < end; k += 1) {
|
|
3030
3030
|
breaks[k] = true;
|
|
3031
3031
|
}
|
|
@@ -3088,30 +3088,30 @@ function evidenceFits(previous, grid, slotCount, totalBeats, segmentation, harmo
|
|
|
3088
3088
|
return previous.grid.origin === grid.origin && previous.grid.slotBeats === grid.slotBeats && previous.slotCount === slotCount && previous.totalBeats === totalBeats && previous.segmentation === segmentation && previous.harmonicRhythm === harmonicRhythm && previous.keyGiven === keyGiven;
|
|
3089
3089
|
}
|
|
3090
3090
|
function analyzeTimeline(notes, opts = {}, previous, dirty) {
|
|
3091
|
-
const meters =
|
|
3092
|
-
const harmonicRhythm = _nullishCoalesce(opts.harmonicRhythm, () => (
|
|
3093
|
-
|
|
3091
|
+
const meters = _chunkS5BKZZGMcjs.resolveMeters.call(void 0, opts, "timeline meters");
|
|
3092
|
+
const harmonicRhythm = _nullishCoalesce(opts.harmonicRhythm, () => ( _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, 0, meters)));
|
|
3093
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, harmonicRhythm, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "harmonic rhythm");
|
|
3094
3094
|
const segmentation = _nullishCoalesce(opts.segmentation, () => ( "dynamic"));
|
|
3095
|
-
const gridUnit =
|
|
3095
|
+
const gridUnit = _chunkS5BKZZGMcjs.metricGridUnit.call(void 0, meters);
|
|
3096
3096
|
const minChordBeats = _nullishCoalesce(opts.minChordBeats, () => ( gridUnit));
|
|
3097
|
-
|
|
3097
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, minChordBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "minChordBeats");
|
|
3098
3098
|
const budget = opts.budget;
|
|
3099
3099
|
const noteOptions = { allowNonPositiveDuration: true, budget };
|
|
3100
3100
|
if (opts.pickupBeats !== void 0) {
|
|
3101
|
-
|
|
3101
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, opts.pickupBeats, 0, Number.MAX_SAFE_INTEGER, "timeline pickupBeats");
|
|
3102
3102
|
noteOptions.minStartBeat = -opts.pickupBeats;
|
|
3103
3103
|
}
|
|
3104
|
-
|
|
3105
|
-
const sounding =
|
|
3104
|
+
_chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, notes, "timeline notes", noteOptions);
|
|
3105
|
+
const sounding = _chunk35NBV2FTcjs.sortedNoteEvents.call(void 0, notes.filter((note) => note.durationBeat > 0));
|
|
3106
3106
|
const lastNoteEnd = sounding.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), 0);
|
|
3107
3107
|
const totalBeats = _nullishCoalesce(opts.totalBeats, () => ( lastNoteEnd));
|
|
3108
|
-
|
|
3108
|
+
_chunkS5BKZZGMcjs.assertRange.call(void 0, totalBeats, 0, Number.MAX_SAFE_INTEGER, "timeline totalBeats");
|
|
3109
3109
|
const slotBeats = segmentation === "grid" ? harmonicRhythm : slotBeatsWithin(gridUnit, minChordBeats, harmonicRhythm);
|
|
3110
3110
|
const { origin, startBeat: musicStart } = gridForNotes(sounding, slotBeats);
|
|
3111
3111
|
const grid = { origin, slotBeats };
|
|
3112
|
-
const slotCount = Math.max(0, Math.ceil((totalBeats - grid.origin) / slotBeats -
|
|
3112
|
+
const slotCount = Math.max(0, Math.ceil((totalBeats - grid.origin) / slotBeats - _chunkS5BKZZGMcjs.BEAT_EPS));
|
|
3113
3113
|
const dynamic = segmentation === "dynamic";
|
|
3114
|
-
|
|
3114
|
+
_chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0,
|
|
3115
3115
|
dynamic ? slotCount * LEXICON_SIZE : slotCount,
|
|
3116
3116
|
"timeline windows",
|
|
3117
3117
|
budget
|
|
@@ -3120,13 +3120,13 @@ function analyzeTimeline(notes, opts = {}, previous, dirty) {
|
|
|
3120
3120
|
{
|
|
3121
3121
|
startBeat: musicStart,
|
|
3122
3122
|
endBeat: totalBeats,
|
|
3123
|
-
key:
|
|
3123
|
+
key: _chunk3R3QVKY5cjs.resolveKey.call(void 0, opts.key),
|
|
3124
3124
|
confidence: 1
|
|
3125
3125
|
}
|
|
3126
3126
|
] : keyTimelineFromNotes(sounding, { meters, totalBeats, budget });
|
|
3127
|
-
const prevailingKey = _nullishCoalesce(prevailingKeyOf(keys), () => (
|
|
3127
|
+
const prevailingKey = _nullishCoalesce(prevailingKeyOf(keys), () => ( _chunk3R3QVKY5cjs.resolveKey.call(void 0, _chunk3R3QVKY5cjs.majorKey.call(void 0, 0))));
|
|
3128
3128
|
const keyAt = keyLookup(keys, prevailingKey);
|
|
3129
|
-
const scaleAt = (beat) =>
|
|
3129
|
+
const scaleAt = (beat) => _chunk3R3QVKY5cjs.scaleOf.call(void 0, keyAt(beat));
|
|
3130
3130
|
const segments = [];
|
|
3131
3131
|
const segmentConfidence = [];
|
|
3132
3132
|
const slotNotes = bucketNotesBySlot(sounding, grid, slotCount, {
|
|
@@ -3200,7 +3200,7 @@ function analyzeTimeline(notes, opts = {}, previous, dirty) {
|
|
|
3200
3200
|
}
|
|
3201
3201
|
const { start, end } = bounds;
|
|
3202
3202
|
const last = segments[segments.length - 1];
|
|
3203
|
-
if (last && sameChord(last.chord, inferred.chord) && Math.abs(last.endBeat - start) <
|
|
3203
|
+
if (last && sameChord(last.chord, inferred.chord) && Math.abs(last.endBeat - start) < _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
3204
3204
|
const lastLength = last.endBeat - last.startBeat;
|
|
3205
3205
|
const length = end - start;
|
|
3206
3206
|
const lastConfidence = _nullishCoalesce(segmentConfidence[segmentConfidence.length - 1], () => ( 0));
|
|
@@ -3241,11 +3241,11 @@ function detectCadences(timeline, key) {
|
|
|
3241
3241
|
if (!prev || !cur) {
|
|
3242
3242
|
continue;
|
|
3243
3243
|
}
|
|
3244
|
-
if (Math.abs(cur.startBeat - prev.endBeat) >
|
|
3244
|
+
if (Math.abs(cur.startBeat - prev.endBeat) > _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
3245
3245
|
continue;
|
|
3246
3246
|
}
|
|
3247
3247
|
const before = timeline.segments[i - 2];
|
|
3248
|
-
const approach = before !== void 0 && Math.abs(prev.startBeat - before.endBeat) <=
|
|
3248
|
+
const approach = before !== void 0 && Math.abs(prev.startBeat - before.endBeat) <= _chunkS5BKZZGMcjs.BEAT_EPS ? before.chord : void 0;
|
|
3249
3249
|
const key2 = keyAt(cur.startBeat);
|
|
3250
3250
|
const cadence = detectCadence(prev.chord, cur.chord, key2, {
|
|
3251
3251
|
...approach === void 0 ? {} : { approach }
|
|
@@ -3255,7 +3255,7 @@ function detectCadences(timeline, key) {
|
|
|
3255
3255
|
}
|
|
3256
3256
|
if (cadence.type === "half" && isCadentialSixFour(prev.chord, cur.chord, key2)) {
|
|
3257
3257
|
const next = timeline.segments[i + 1];
|
|
3258
|
-
if (next !== void 0 && Math.abs(next.startBeat - cur.endBeat) <=
|
|
3258
|
+
if (next !== void 0 && Math.abs(next.startBeat - cur.endBeat) <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
3259
3259
|
const onward = detectCadence(cur.chord, next.chord, keyAt(next.startBeat)).type;
|
|
3260
3260
|
if (onward === "authentic" || onward === "deceptive") {
|
|
3261
3261
|
continue;
|
|
@@ -3326,4 +3326,4 @@ function detectCadences(timeline, key) {
|
|
|
3326
3326
|
|
|
3327
3327
|
|
|
3328
3328
|
exports.HUMANIZE_ADJACENCY = HUMANIZE_ADJACENCY; exports.sameInstant = sameInstant; exports.adjacent = adjacent; exports.hasEnded = hasEnded; exports.windowWeights = windowWeights; exports.MODAL_SCALE_NAMES = MODAL_SCALE_NAMES; exports.detectChord = detectChord; exports.detectChordBest = detectChordBest; exports.detectKey = detectKey; exports.detectKeyFromNotes = detectKeyFromNotes; exports.detectKeyBest = detectKeyBest; exports.augmentedSixthChord = augmentedSixthChord; exports.augmentedSixthKind = augmentedSixthKind; exports.augmentedSixthFromPitchClasses = augmentedSixthFromPitchClasses; exports.spellAugmentedSixth = spellAugmentedSixth; exports.isCadentialSixFour = isCadentialSixFour; exports.detectCadence = detectCadence; exports.isBorrowedChord = isBorrowedChord; exports.borrowedSource = borrowedSource; exports.isAppliedDominant = isAppliedDominant; exports.romanToChord = romanToChord; exports.chordToRoman = chordToRoman; exports.explainRoman = explainRoman; exports.isMinorKey = isMinorKey; exports.functionOf = functionOf; exports.isDiatonic = isDiatonic; exports.parallelKey = parallelKey; exports.analyzeChord = analyzeChord; exports.secondaryDominant = secondaryDominant; exports.secondaryDominantOf = secondaryDominantOf; exports.pivotChords = pivotChords; exports.clamp01 = clamp01; exports.floorMod = floorMod; exports.firstSoundingBeat = firstSoundingBeat; exports.lastBarOf = lastBarOf; exports.sliceBars = sliceBars; exports.weightSimilarity = weightSimilarity; exports.harmonicNovelty = harmonicNovelty; exports.combineEvidence = combineEvidence; exports.gridForNotes = gridForNotes; exports.barGridStart = barGridStart; exports.keyTimelineFromNotes = keyTimelineFromNotes; exports.detectModulations = detectModulations; exports.attachPivots = attachPivots; exports.keyLookup = keyLookup; exports.prevailingKeyOf = prevailingKeyOf; exports.keyScaleAt = keyScaleAt; exports.toVoiceNotes = toVoiceNotes; exports.analyzeVoice = analyzeVoice; exports.assertChordTimeline = assertChordTimeline; exports.chordTimelineFromChords = chordTimelineFromChords; exports.chordAtBeat = chordAtBeat; exports.segmentStartingAt = segmentStartingAt; exports.chordTimelineFromNotes = chordTimelineFromNotes; exports.dirtySlotsFor = dirtySlotsFor; exports.analyzeTimeline = analyzeTimeline; exports.detectCadences = detectCadences;
|
|
3329
|
-
//# sourceMappingURL=chunk-
|
|
3329
|
+
//# sourceMappingURL=chunk-SGLEQVJH.cjs.map
|