@libraz/libcantus 1.3.0 → 1.4.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/NOTICE +63 -0
- package/README.md +3 -1
- package/README_ja.md +13 -11
- package/dist/analyze/index.cjs +7 -7
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +14 -12
- package/dist/analyze/index.d.ts +14 -12
- package/dist/analyze/index.js +6 -6
- package/dist/{chunk-NB25P3EH.js → chunk-2G5MCGYU.js} +33 -11
- package/dist/chunk-2G5MCGYU.js.map +1 -0
- package/dist/{chunk-NM7UAMC3.cjs → chunk-3FDBMIPR.cjs} +64 -64
- package/dist/chunk-3FDBMIPR.cjs.map +1 -0
- package/dist/{chunk-YFA7X2F6.cjs → chunk-3MDOEFIQ.cjs} +411 -327
- package/dist/chunk-3MDOEFIQ.cjs.map +1 -0
- package/dist/{chunk-IPEF6NWB.js → chunk-5MWRBYAT.js} +278 -154
- package/dist/chunk-5MWRBYAT.js.map +1 -0
- package/dist/{chunk-B2PW6EHN.cjs → chunk-6TTBEON3.cjs} +1253 -889
- package/dist/chunk-6TTBEON3.cjs.map +1 -0
- package/dist/{chunk-UMWZ4ZET.js → chunk-7NQ6AL3H.js} +4 -4
- package/dist/chunk-7NQ6AL3H.js.map +1 -0
- package/dist/{chunk-PWC4CRWT.cjs → chunk-E3QO3UET.cjs} +31 -23
- package/dist/chunk-E3QO3UET.cjs.map +1 -0
- package/dist/{chunk-GNVN4PPJ.js → chunk-FJFULJZE.js} +531 -213
- package/dist/chunk-FJFULJZE.js.map +1 -0
- package/dist/{chunk-CPMB7P75.js → chunk-FK3DGAIZ.js} +608 -244
- package/dist/chunk-FK3DGAIZ.js.map +1 -0
- package/dist/chunk-GEDTJHAC.cjs.map +1 -1
- package/dist/{chunk-RFIBF2RR.js → chunk-H7FVMBUC.js} +138 -65
- package/dist/chunk-H7FVMBUC.js.map +1 -0
- package/dist/{chunk-4R2LWV7E.cjs → chunk-HYSVSFNI.cjs} +664 -540
- package/dist/chunk-HYSVSFNI.cjs.map +1 -0
- package/dist/{chunk-35NBV2FT.cjs → chunk-KMYGRFZ6.cjs} +47 -24
- package/dist/chunk-KMYGRFZ6.cjs.map +1 -0
- package/dist/{chunk-IFZDWIKM.cjs → chunk-LQZQDBCD.cjs} +1048 -730
- package/dist/chunk-LQZQDBCD.cjs.map +1 -0
- package/dist/{chunk-PM4XJE2Y.cjs → chunk-P3CPXAJ5.cjs} +76 -54
- package/dist/chunk-P3CPXAJ5.cjs.map +1 -0
- package/dist/{chunk-S5BKZZGM.cjs → chunk-S3QELJUE.cjs} +72 -56
- package/dist/chunk-S3QELJUE.cjs.map +1 -0
- package/dist/{chunk-PUKJP2Z5.js → chunk-TXFWSU5D.js} +31 -8
- package/dist/chunk-TXFWSU5D.js.map +1 -0
- package/dist/{chunk-76ZBTRG2.cjs → chunk-U4EQTDGN.cjs} +258 -218
- package/dist/chunk-U4EQTDGN.cjs.map +1 -0
- package/dist/chunk-UGLFDG7L.cjs.map +1 -1
- package/dist/{chunk-MLBPXA4Z.js → chunk-UTE5A36R.js} +198 -114
- package/dist/chunk-UTE5A36R.js.map +1 -0
- package/dist/{chunk-ZBUROTJQ.js → chunk-UZKQISRF.js} +17 -9
- package/dist/chunk-UZKQISRF.js.map +1 -0
- package/dist/{chunk-7KG3RTYS.js → chunk-VL5NXVCN.js} +281 -155
- package/dist/chunk-VL5NXVCN.js.map +1 -0
- package/dist/{chunk-CGBADIO5.cjs → chunk-WOMCXN2W.cjs} +328 -202
- package/dist/chunk-WOMCXN2W.cjs.map +1 -0
- package/dist/{chunk-3R3QVKY5.cjs → chunk-YDGMWH43.cjs} +397 -324
- package/dist/chunk-YDGMWH43.cjs.map +1 -0
- package/dist/{chunk-AGOVW7U6.js → chunk-YYVXRV3V.js} +72 -56
- package/dist/chunk-YYVXRV3V.js.map +1 -0
- package/dist/{chunk-M5RYMAFI.js → chunk-ZLNSH4UL.js} +71 -31
- package/dist/chunk-ZLNSH4UL.js.map +1 -0
- package/dist/{coerce-DRERzdve.d.cts → coerce-CUhHc3Tu.d.ts} +16 -8
- package/dist/{coerce-DP0vYu-x.d.ts → coerce-Ytt2Eiq9.d.cts} +16 -8
- package/dist/core/index.cjs +5 -5
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +9 -8
- package/dist/core/index.d.ts +9 -8
- package/dist/core/index.js +4 -4
- package/dist/generate/index.cjs +8 -8
- package/dist/generate/index.cjs.map +1 -1
- package/dist/generate/index.d.cts +28 -18
- package/dist/generate/index.d.ts +28 -18
- package/dist/generate/index.js +7 -7
- package/dist/{index-BMweUlm5.d.cts → index-5VJgKz_Q.d.cts} +6 -2
- package/dist/{index-BHIUyjhZ.d.ts → index-BLuDesVG.d.ts} +20 -13
- package/dist/{index-B9QLziDe.d.cts → index-BV6APVa6.d.cts} +20 -13
- package/dist/{index-CL4b4gUQ.d.ts → index-Bf0Sv8a9.d.ts} +6 -2
- package/dist/{index-Dw2DP7vm.d.ts → index-BkT21EMv.d.cts} +3 -2
- package/dist/{index-BL5N2Oyz.d.cts → index-C7KCaTRz.d.ts} +3 -2
- package/dist/{index-Cy15oTvh.d.ts → index-C9MYbuKS.d.cts} +7 -3
- package/dist/{index-Cy15oTvh.d.cts → index-C9MYbuKS.d.ts} +7 -3
- package/dist/{index-CY-3NVfy.d.cts → index-DVInzCDS.d.cts} +53 -29
- package/dist/{index-9eoQs2C1.d.ts → index-Dg-SAfhz.d.ts} +6 -4
- package/dist/{index-zaZdmnU4.d.ts → index-jgeug9EA.d.ts} +53 -29
- package/dist/{index-cHvbYgJI.d.cts → index-pQihL4z7.d.cts} +6 -4
- package/dist/index.cjs +13 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +12 -12
- package/dist/{masks-Cc7-MzzY.d.ts → masks-BnzXnBj0.d.cts} +3 -2
- package/dist/{masks-pADfTOiD.d.cts → masks-tycmkrgs.d.ts} +3 -2
- package/dist/model/index.cjs +12 -12
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +63 -48
- package/dist/model/index.d.ts +63 -48
- package/dist/model/index.js +11 -11
- package/dist/{positional-DJgs6ltD.d.ts → positional-CscpxtlE.d.cts} +3 -2
- package/dist/{positional-DMZer-FM.d.cts → positional-DLnfUgqG.d.ts} +3 -2
- package/dist/{profile-DLdlIpS9.d.ts → profile-B4WqcM4H.d.ts} +25 -17
- package/dist/{profile-CQMEqdH9.d.cts → profile-BJd1XkPB.d.cts} +25 -17
- package/dist/theory/index.cjs +5 -5
- package/dist/theory/index.cjs.map +1 -1
- package/dist/theory/index.d.cts +18 -14
- package/dist/theory/index.d.ts +18 -14
- package/dist/theory/index.js +4 -4
- package/dist/{types-D-XgxGvp.d.cts → types-7mGFwvMm.d.ts} +45 -22
- package/dist/{types-Dh7C064C.d.ts → types-_ofpb2be.d.cts} +45 -22
- package/package.json +13 -13
- package/dist/chunk-35NBV2FT.cjs.map +0 -1
- package/dist/chunk-3R3QVKY5.cjs.map +0 -1
- package/dist/chunk-4R2LWV7E.cjs.map +0 -1
- package/dist/chunk-76ZBTRG2.cjs.map +0 -1
- package/dist/chunk-7KG3RTYS.js.map +0 -1
- package/dist/chunk-AGOVW7U6.js.map +0 -1
- package/dist/chunk-B2PW6EHN.cjs.map +0 -1
- package/dist/chunk-CGBADIO5.cjs.map +0 -1
- package/dist/chunk-CPMB7P75.js.map +0 -1
- package/dist/chunk-GNVN4PPJ.js.map +0 -1
- package/dist/chunk-IFZDWIKM.cjs.map +0 -1
- package/dist/chunk-IPEF6NWB.js.map +0 -1
- package/dist/chunk-M5RYMAFI.js.map +0 -1
- package/dist/chunk-MLBPXA4Z.js.map +0 -1
- package/dist/chunk-NB25P3EH.js.map +0 -1
- package/dist/chunk-NM7UAMC3.cjs.map +0 -1
- package/dist/chunk-PM4XJE2Y.cjs.map +0 -1
- package/dist/chunk-PUKJP2Z5.js.map +0 -1
- package/dist/chunk-PWC4CRWT.cjs.map +0 -1
- package/dist/chunk-RFIBF2RR.js.map +0 -1
- package/dist/chunk-S5BKZZGM.cjs.map +0 -1
- package/dist/chunk-UMWZ4ZET.js.map +0 -1
- package/dist/chunk-YFA7X2F6.cjs.map +0 -1
- package/dist/chunk-ZBUROTJQ.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
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 _chunk35NBV2FTcjs = require('./chunk-35NBV2FT.cjs');
|
|
4
3
|
|
|
4
|
+
var _chunkKMYGRFZ6cjs = require('./chunk-KMYGRFZ6.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
@@ -48,11 +48,11 @@ var _chunk35NBV2FTcjs = require('./chunk-35NBV2FT.cjs');
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
var _chunk3R3QVKY5cjs = require('./chunk-3R3QVKY5.cjs');
|
|
52
51
|
|
|
53
52
|
|
|
54
53
|
|
|
55
54
|
|
|
55
|
+
var _chunkYDGMWH43cjs = require('./chunk-YDGMWH43.cjs');
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
|
|
@@ -90,18 +90,24 @@ var _chunk3R3QVKY5cjs = require('./chunk-3R3QVKY5.cjs');
|
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
var _chunkS3QELJUEcjs = require('./chunk-S3QELJUE.cjs');
|
|
94
100
|
|
|
95
101
|
// src/analyze/detect/modes.ts
|
|
96
102
|
var MODAL_CANDIDATES = Object.freeze([
|
|
97
|
-
{ scaleName: "dorian", mode: "minor", mask:
|
|
98
|
-
{ scaleName: "phrygian", mode: "minor", mask:
|
|
99
|
-
{ scaleName: "lydian", mode: "major", mask:
|
|
100
|
-
{ scaleName: "mixolydian", mode: "major", mask:
|
|
103
|
+
{ scaleName: "dorian", mode: "minor", mask: _chunkYDGMWH43cjs.DORIAN_MASK, substitutions: [[8, 9]] },
|
|
104
|
+
{ scaleName: "phrygian", mode: "minor", mask: _chunkYDGMWH43cjs.PHRYGIAN_MASK, substitutions: [[2, 1]] },
|
|
105
|
+
{ scaleName: "lydian", mode: "major", mask: _chunkYDGMWH43cjs.LYDIAN_MASK, substitutions: [[5, 6]] },
|
|
106
|
+
{ scaleName: "mixolydian", mode: "major", mask: _chunkYDGMWH43cjs.MIXOLYDIAN_MASK, substitutions: [[11, 10]] },
|
|
101
107
|
{
|
|
102
108
|
scaleName: "locrian",
|
|
103
109
|
mode: "minor",
|
|
104
|
-
mask:
|
|
110
|
+
mask: _chunkYDGMWH43cjs.LOCRIAN_MASK,
|
|
105
111
|
substitutions: [
|
|
106
112
|
[2, 1],
|
|
107
113
|
[7, 6]
|
|
@@ -128,12 +134,12 @@ function resolveModalCandidates(modes) {
|
|
|
128
134
|
return MODAL_CANDIDATES;
|
|
129
135
|
}
|
|
130
136
|
if (!Array.isArray(modes)) {
|
|
131
|
-
throw new (0,
|
|
137
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("modes must be a boolean or an array of mode names");
|
|
132
138
|
}
|
|
133
139
|
const requested = new Set(modes);
|
|
134
140
|
for (const name of requested) {
|
|
135
141
|
if (!MODAL_SCALE_NAMES.some((known) => known === name)) {
|
|
136
|
-
throw new (0,
|
|
142
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
137
143
|
`unknown mode '${String(name)}'; expected one of ${MODAL_SCALE_NAMES.join(", ")}`
|
|
138
144
|
);
|
|
139
145
|
}
|
|
@@ -144,7 +150,7 @@ function resolveModalCandidates(modes) {
|
|
|
144
150
|
// src/analyze/adjacency.ts
|
|
145
151
|
var HUMANIZE_ADJACENCY = 0.05;
|
|
146
152
|
function sameInstant(beat, other) {
|
|
147
|
-
return Math.abs(beat - other) <=
|
|
153
|
+
return Math.abs(beat - other) <= _chunkS3QELJUEcjs.BEAT_EPS;
|
|
148
154
|
}
|
|
149
155
|
function adjacent(prevEnd, nextStart) {
|
|
150
156
|
return Math.abs(nextStart - prevEnd) <= HUMANIZE_ADJACENCY;
|
|
@@ -158,7 +164,7 @@ var MAX_VELOCITY = 127;
|
|
|
158
164
|
var ACCENT_DIVISOR = 3;
|
|
159
165
|
function noteWeight(note, beats, meter) {
|
|
160
166
|
const velocityFactor = note.velocity !== void 0 ? note.velocity / MAX_VELOCITY : 1;
|
|
161
|
-
const accent = meter === void 0 ? 1 : 1 +
|
|
167
|
+
const accent = meter === void 0 ? 1 : 1 + _chunkS3QELJUEcjs.metricWeight.call(void 0, note.startBeat, meter) / ACCENT_DIVISOR;
|
|
162
168
|
return beats * velocityFactor * accent;
|
|
163
169
|
}
|
|
164
170
|
function bucketNotesBySlot(notes, grid, slotCount, opts) {
|
|
@@ -171,7 +177,7 @@ function bucketNotesBySlot(notes, grid, slotCount, opts) {
|
|
|
171
177
|
Math.ceil((note.startBeat + note.durationBeat - grid.origin) / grid.slotBeats)
|
|
172
178
|
);
|
|
173
179
|
memberships += Math.max(0, lastExclusive - first);
|
|
174
|
-
|
|
180
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, memberships, opts.name, opts.budget);
|
|
175
181
|
for (let slot = first; slot < lastExclusive; slot += 1) {
|
|
176
182
|
_optionalChain([buckets, 'access', _2 => _2[slot], 'optionalAccess', _3 => _3.push, 'call', _4 => _4(note)]);
|
|
177
183
|
}
|
|
@@ -184,14 +190,14 @@ function windowWeights(notes, windowStart, windowEnd, meter) {
|
|
|
184
190
|
for (const note of notes) {
|
|
185
191
|
const noteEnd = note.startBeat + note.durationBeat;
|
|
186
192
|
const overlap = Math.min(noteEnd, windowEnd) - Math.max(note.startBeat, windowStart);
|
|
187
|
-
if (overlap <=
|
|
193
|
+
if (overlap <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
188
194
|
continue;
|
|
189
195
|
}
|
|
190
|
-
const onsetInWindow = note.startBeat >= windowStart -
|
|
191
|
-
const pc =
|
|
196
|
+
const onsetInWindow = note.startBeat >= windowStart - _chunkS3QELJUEcjs.BEAT_EPS && note.startBeat < windowEnd - _chunkS3QELJUEcjs.BEAT_EPS;
|
|
197
|
+
const pc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, note.pitch);
|
|
192
198
|
const weight = noteWeight(note, overlap, onsetInWindow ? meter : void 0);
|
|
193
199
|
weights[pc] = (_nullishCoalesce(weights[pc], () => ( 0))) + weight;
|
|
194
|
-
if (weight >
|
|
200
|
+
if (weight > _chunkS3QELJUEcjs.BEAT_EPS && note.pitch < lowestPitch) {
|
|
195
201
|
lowestPitch = note.pitch;
|
|
196
202
|
}
|
|
197
203
|
}
|
|
@@ -204,6 +210,30 @@ function windowWeights(notes, windowStart, windowEnd, meter) {
|
|
|
204
210
|
return { weights, totalWeight, maxWeight, lowestPitch };
|
|
205
211
|
}
|
|
206
212
|
|
|
213
|
+
// src/analyze/detect/internal.ts
|
|
214
|
+
var MINOR_VARIANTS = [
|
|
215
|
+
{ variant: "natural", mask: _chunkYDGMWH43cjs.NATURAL_MINOR_MASK, scaleName: "naturalMinor" },
|
|
216
|
+
{ variant: "harmonic", mask: _chunkYDGMWH43cjs.HARMONIC_MINOR_MASK, scaleName: "harmonicMinor" },
|
|
217
|
+
{ variant: "melodic", mask: _chunkYDGMWH43cjs.MELODIC_MINOR_MASK, scaleName: "melodicMinor" }
|
|
218
|
+
];
|
|
219
|
+
var MAJOR_VARIANTS = [
|
|
220
|
+
{ variant: "major", mask: _chunkYDGMWH43cjs.MAJOR_MASK, scaleName: "major" }
|
|
221
|
+
];
|
|
222
|
+
var SCALE_NAME_ORDER = [
|
|
223
|
+
"major",
|
|
224
|
+
"naturalMinor",
|
|
225
|
+
"harmonicMinor",
|
|
226
|
+
"melodicMinor",
|
|
227
|
+
"dorian",
|
|
228
|
+
"phrygian",
|
|
229
|
+
"lydian",
|
|
230
|
+
"mixolydian",
|
|
231
|
+
"locrian"
|
|
232
|
+
];
|
|
233
|
+
var EXPLAINED_RIVALS = 3;
|
|
234
|
+
var SCORE_DIGITS = 2;
|
|
235
|
+
var MAX_SCORE_DIGITS = 6;
|
|
236
|
+
|
|
207
237
|
// src/analyze/detect/profiles.ts
|
|
208
238
|
var KRUMHANSL_KESSLER_PROFILE = {
|
|
209
239
|
major: [6.35, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88],
|
|
@@ -226,12 +256,12 @@ var NAMED_PROFILES = {
|
|
|
226
256
|
};
|
|
227
257
|
function assertProfileVector(vector, name) {
|
|
228
258
|
if (vector.length !== PROFILE_LENGTH) {
|
|
229
|
-
throw new (0,
|
|
259
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must have ${PROFILE_LENGTH} entries`);
|
|
230
260
|
}
|
|
231
261
|
for (let index = 0; index < vector.length; index += 1) {
|
|
232
262
|
const value = vector[index];
|
|
233
263
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
234
|
-
throw new (0,
|
|
264
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}[${index}] must be a finite number`);
|
|
235
265
|
}
|
|
236
266
|
}
|
|
237
267
|
}
|
|
@@ -242,18 +272,18 @@ function resolveKeyProfile(profile) {
|
|
|
242
272
|
if (typeof profile === "string") {
|
|
243
273
|
const named = NAMED_PROFILES[profile];
|
|
244
274
|
if (named === void 0) {
|
|
245
|
-
throw new (0,
|
|
275
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
246
276
|
`unknown key profile '${profile}'; expected one of ${Object.keys(NAMED_PROFILES).join(", ")}`
|
|
247
277
|
);
|
|
248
278
|
}
|
|
249
279
|
return named;
|
|
250
280
|
}
|
|
251
281
|
if (typeof profile !== "object" || profile === null) {
|
|
252
|
-
throw new (0,
|
|
282
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("profile must be a profile name or a { major, minor } pair");
|
|
253
283
|
}
|
|
254
284
|
const { major, minor } = profile;
|
|
255
285
|
if (!Array.isArray(major) || !Array.isArray(minor)) {
|
|
256
|
-
throw new (0,
|
|
286
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("profile must carry a major and a minor vector");
|
|
257
287
|
}
|
|
258
288
|
assertProfileVector(major, "profile.major");
|
|
259
289
|
assertProfileVector(minor, "profile.minor");
|
|
@@ -302,45 +332,54 @@ function profileScore(dist, vector, tonic) {
|
|
|
302
332
|
}
|
|
303
333
|
|
|
304
334
|
// src/analyze/detect/index.ts
|
|
335
|
+
var CHORD_INPUT_KINDS = [
|
|
336
|
+
"auto",
|
|
337
|
+
"midi",
|
|
338
|
+
"pitchClass"
|
|
339
|
+
];
|
|
305
340
|
function uniquePitchClasses(pitches) {
|
|
306
|
-
return [...new Set(pitches.map(
|
|
341
|
+
return [...new Set(pitches.map(_chunkS3QELJUEcjs.pitchClassOf))].sort((a, b) => a - b);
|
|
307
342
|
}
|
|
308
343
|
function assertPitches(pitches, name, budget = void 0) {
|
|
309
|
-
|
|
310
|
-
|
|
344
|
+
_chunkS3QELJUEcjs.assertArray.call(void 0, pitches, name);
|
|
345
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, pitches.length, name, budget);
|
|
311
346
|
for (let index = 0; index < pitches.length; index += 1) {
|
|
312
|
-
|
|
347
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, _nullishCoalesce(pitches[index], () => ( Number.NaN)), `pitches[${index}]`);
|
|
313
348
|
}
|
|
314
349
|
}
|
|
315
350
|
function detectChord(pitches, opts = {}) {
|
|
316
|
-
const asked =
|
|
351
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
317
352
|
assertPitches(pitches, "chord detection pitches");
|
|
318
|
-
|
|
353
|
+
const askedKind = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(asked.input, () => ( "auto")), CHORD_INPUT_KINDS, "input");
|
|
354
|
+
if (asked.bassPc !== void 0) _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, asked.bassPc, "bassPc");
|
|
319
355
|
const input = uniquePitchClasses(pitches);
|
|
320
356
|
if (input.length === 0) {
|
|
321
357
|
return [];
|
|
322
358
|
}
|
|
323
|
-
const inputKind =
|
|
324
|
-
const bassPc = asked.bassPc !== void 0 ?
|
|
359
|
+
const inputKind = askedKind === "auto" ? pitches.every((pitch) => Number.isInteger(pitch) && pitch >= 0 && pitch <= 11) ? "pitchClass" : "midi" : askedKind;
|
|
360
|
+
const bassPc = asked.bassPc !== void 0 ? _chunkS3QELJUEcjs.pitchClassOf.call(void 0, asked.bassPc) : inputKind === "midi" ? _chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitches.reduce((lowest, pitch) => Math.min(lowest, pitch), Infinity)) : void 0;
|
|
325
361
|
const inputSet = new Set(input);
|
|
326
362
|
const matches = [];
|
|
327
|
-
const qualities =
|
|
363
|
+
const qualities = _chunkYDGMWH43cjs.chordQualities.call(void 0, );
|
|
328
364
|
const toneCounts = new Map(
|
|
329
|
-
qualities.map((quality) => [quality,
|
|
365
|
+
qualities.map((quality) => [quality, _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, 0, quality)).length])
|
|
330
366
|
);
|
|
331
367
|
const qualityRank = new Map(qualities.map((quality, index) => [quality, index]));
|
|
332
368
|
for (const rootPc of input) {
|
|
333
369
|
for (const quality of qualities) {
|
|
334
|
-
const chord =
|
|
335
|
-
const tones =
|
|
370
|
+
const chord = _chunkYDGMWH43cjs.makeChord.call(void 0, rootPc, quality);
|
|
371
|
+
const tones = _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord);
|
|
336
372
|
const toneSet = new Set(tones);
|
|
337
373
|
const missingPcs = tones.filter((pc) => !inputSet.has(pc));
|
|
338
|
-
const fifthPc =
|
|
374
|
+
const fifthPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc + 7);
|
|
339
375
|
if (missingPcs.length > 1 || missingPcs.length === 1 && missingPcs[0] !== fifthPc) {
|
|
340
376
|
continue;
|
|
341
377
|
}
|
|
378
|
+
if (tones.length - missingPcs.length < 2) {
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
342
381
|
const extraPcs = input.filter((pc) => !toneSet.has(pc));
|
|
343
|
-
const bassIndex = bassPc === void 0 ? -1 : chord.intervals.findIndex((iv) =>
|
|
382
|
+
const bassIndex = bassPc === void 0 ? -1 : chord.intervals.findIndex((iv) => _chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc + iv) === bassPc);
|
|
344
383
|
const inversion = bassPc === void 0 || bassIndex < 0 ? null : bassIndex;
|
|
345
384
|
const match = {
|
|
346
385
|
rootPc,
|
|
@@ -385,33 +424,11 @@ function detectChordBest(pitches, opts = {}) {
|
|
|
385
424
|
if (!best) {
|
|
386
425
|
return null;
|
|
387
426
|
}
|
|
388
|
-
return
|
|
427
|
+
return _chunkYDGMWH43cjs.makeChord.call(void 0, best.rootPc, best.quality, best.bassPc);
|
|
389
428
|
}
|
|
390
|
-
var MINOR_VARIANTS = [
|
|
391
|
-
{ variant: "natural", mask: _chunk3R3QVKY5cjs.NATURAL_MINOR_MASK, scaleName: "naturalMinor" },
|
|
392
|
-
{ variant: "harmonic", mask: _chunk3R3QVKY5cjs.HARMONIC_MINOR_MASK, scaleName: "harmonicMinor" },
|
|
393
|
-
{ variant: "melodic", mask: _chunk3R3QVKY5cjs.MELODIC_MINOR_MASK, scaleName: "melodicMinor" }
|
|
394
|
-
];
|
|
395
|
-
var MAJOR_VARIANTS = [
|
|
396
|
-
{ variant: "major", mask: _chunk3R3QVKY5cjs.MAJOR_MASK, scaleName: "major" }
|
|
397
|
-
];
|
|
398
|
-
var SCALE_NAME_ORDER = [
|
|
399
|
-
"major",
|
|
400
|
-
"naturalMinor",
|
|
401
|
-
"harmonicMinor",
|
|
402
|
-
"melodicMinor",
|
|
403
|
-
"dorian",
|
|
404
|
-
"phrygian",
|
|
405
|
-
"lydian",
|
|
406
|
-
"mixolydian",
|
|
407
|
-
"locrian"
|
|
408
|
-
];
|
|
409
429
|
function scaleNameRank(name) {
|
|
410
430
|
return SCALE_NAME_ORDER.indexOf(name);
|
|
411
431
|
}
|
|
412
|
-
var EXPLAINED_RIVALS = 3;
|
|
413
|
-
var SCORE_DIGITS = 2;
|
|
414
|
-
var MAX_SCORE_DIGITS = 6;
|
|
415
432
|
function quoteScores(rival, winner) {
|
|
416
433
|
let digits = SCORE_DIGITS;
|
|
417
434
|
while (digits < MAX_SCORE_DIGITS && rival.toFixed(digits) === winner.toFixed(digits)) {
|
|
@@ -420,7 +437,7 @@ function quoteScores(rival, winner) {
|
|
|
420
437
|
return `${rival.toFixed(digits)} against ${winner.toFixed(digits)}`;
|
|
421
438
|
}
|
|
422
439
|
function keyLabel(match) {
|
|
423
|
-
const tonic =
|
|
440
|
+
const tonic = _chunkS3QELJUEcjs.formatNote.call(void 0, _chunkYDGMWH43cjs.spelledKeyOf.call(void 0, match.key).tonic);
|
|
424
441
|
const scale = match.scaleName.replace(/([A-Z])/g, " $1").toLowerCase();
|
|
425
442
|
return `${tonic} ${scale}`;
|
|
426
443
|
}
|
|
@@ -451,11 +468,11 @@ function explainMatches(results, inputSize) {
|
|
|
451
468
|
winner.alternatives = results.slice(1, EXPLAINED_RIVALS + 1).map((rival) => ({ label: keyLabel(rival), reason: keyRivalReason(winner, rival) }));
|
|
452
469
|
}
|
|
453
470
|
function detectKey(pitches, opts = {}) {
|
|
454
|
-
const asked =
|
|
471
|
+
const asked = _chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "opts");
|
|
455
472
|
assertPitches(pitches, "key detection pitches", asked.budget);
|
|
456
473
|
const weights = asked.weights;
|
|
457
474
|
if (weights !== void 0 && weights.length !== pitches.length) {
|
|
458
|
-
throw new (0,
|
|
475
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("weights must have one entry per pitch");
|
|
459
476
|
}
|
|
460
477
|
const profile = resolveKeyProfile(opts.profile);
|
|
461
478
|
const modalCandidates = resolveModalCandidates(opts.modes).map((candidate) => ({
|
|
@@ -466,11 +483,11 @@ function detectKey(pitches, opts = {}) {
|
|
|
466
483
|
let total = 0;
|
|
467
484
|
for (let index = 0; index < pitches.length; index += 1) {
|
|
468
485
|
const weight = weights === void 0 ? 1 : _nullishCoalesce(weights[index], () => ( 0));
|
|
469
|
-
|
|
486
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, weight, `weights[${index}]`);
|
|
470
487
|
if (weight <= 0) {
|
|
471
488
|
continue;
|
|
472
489
|
}
|
|
473
|
-
const pc =
|
|
490
|
+
const pc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, _nullishCoalesce(pitches[index], () => ( 0)));
|
|
474
491
|
counts.set(pc, (_nullishCoalesce(counts.get(pc), () => ( 0))) + weight);
|
|
475
492
|
total += weight;
|
|
476
493
|
}
|
|
@@ -551,8 +568,8 @@ function detectKey(pitches, opts = {}) {
|
|
|
551
568
|
return results;
|
|
552
569
|
}
|
|
553
570
|
function detectKeyFromNotes(notes, opts = {}) {
|
|
554
|
-
const asked =
|
|
555
|
-
|
|
571
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
572
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, notes, "key detection notes", {
|
|
556
573
|
allowNonPositiveDuration: true,
|
|
557
574
|
budget: asked.budget
|
|
558
575
|
});
|
|
@@ -574,40 +591,40 @@ function detectKeyBest(pitches, opts = {}) {
|
|
|
574
591
|
|
|
575
592
|
// src/analyze/functional/internal.ts
|
|
576
593
|
function isMinorScale(key) {
|
|
577
|
-
return
|
|
594
|
+
return _chunkYDGMWH43cjs.isMinorMask.call(void 0, key.modeMask12);
|
|
578
595
|
}
|
|
579
596
|
function parallelScale(key) {
|
|
580
597
|
return {
|
|
581
|
-
rootPc:
|
|
582
|
-
modeMask12: isMinorScale(key) ?
|
|
598
|
+
rootPc: _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc),
|
|
599
|
+
modeMask12: isMinorScale(key) ? _chunkYDGMWH43cjs.MAJOR_MASK : _chunkYDGMWH43cjs.NATURAL_MINOR_MASK
|
|
583
600
|
};
|
|
584
601
|
}
|
|
585
602
|
function degreeRootPc(degreeNumber, key) {
|
|
586
|
-
const tones =
|
|
603
|
+
const tones = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, key);
|
|
587
604
|
if (tones.length === 0) {
|
|
588
|
-
return
|
|
605
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
589
606
|
}
|
|
590
607
|
const index = ((degreeNumber - 1) % tones.length + tones.length) % tones.length;
|
|
591
|
-
return _nullishCoalesce(tones[index], () => (
|
|
608
|
+
return _nullishCoalesce(tones[index], () => ( _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc)));
|
|
592
609
|
}
|
|
593
610
|
function loweredDegrees(key) {
|
|
594
|
-
const tones =
|
|
611
|
+
const tones = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, key);
|
|
595
612
|
const out = /* @__PURE__ */ new Set();
|
|
596
613
|
if (tones.length !== 7) {
|
|
597
614
|
return out;
|
|
598
615
|
}
|
|
599
|
-
const major =
|
|
616
|
+
const major = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, { rootPc: _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunkYDGMWH43cjs.MAJOR_MASK });
|
|
600
617
|
for (let index = 0; index < 7; index += 1) {
|
|
601
618
|
const tone = tones[index];
|
|
602
619
|
const majorTone = major[index];
|
|
603
|
-
if (tone !== void 0 && majorTone !== void 0 &&
|
|
620
|
+
if (tone !== void 0 && majorTone !== void 0 && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, majorTone - tone) === 1) {
|
|
604
621
|
out.add(index + 1);
|
|
605
622
|
}
|
|
606
623
|
}
|
|
607
624
|
return out;
|
|
608
625
|
}
|
|
609
626
|
function romanReference(key) {
|
|
610
|
-
return
|
|
627
|
+
return _chunkYDGMWH43cjs.heptatonicFrameOf.call(void 0, key);
|
|
611
628
|
}
|
|
612
629
|
|
|
613
630
|
// src/analyze/functional/augmented-sixth.ts
|
|
@@ -619,30 +636,31 @@ var TONES_ABOVE_BASS = {
|
|
|
619
636
|
german: [0, 4, 7, 10]
|
|
620
637
|
};
|
|
621
638
|
var SPELLED_ABOVE_BASS = {
|
|
622
|
-
italian: ["P1", "M3", "A6"].map((name) =>
|
|
623
|
-
french: ["P1", "M3", "A4", "A6"].map((name) =>
|
|
624
|
-
german: ["P1", "M3", "P5", "A6"].map((name) =>
|
|
639
|
+
italian: ["P1", "M3", "A6"].map((name) => _chunkS3QELJUEcjs.parseInterval.call(void 0, name)),
|
|
640
|
+
french: ["P1", "M3", "A4", "A6"].map((name) => _chunkS3QELJUEcjs.parseInterval.call(void 0, name)),
|
|
641
|
+
german: ["P1", "M3", "P5", "A6"].map((name) => _chunkS3QELJUEcjs.parseInterval.call(void 0, name))
|
|
625
642
|
};
|
|
626
|
-
var BASS_INTERVAL =
|
|
643
|
+
var BASS_INTERVAL = _chunkS3QELJUEcjs.parseInterval.call(void 0, "m6");
|
|
627
644
|
var CHORD_SHAPE = {
|
|
628
645
|
italian: { rootAboveBass: 0, quality: "dom7", intervals: [0, 4, 10] },
|
|
629
646
|
french: { rootAboveBass: 6, quality: "7b5", intervals: [0, 4, 6, 10] },
|
|
630
647
|
german: { rootAboveBass: 0, quality: "dom7", intervals: [0, 4, 7, 10] }
|
|
631
648
|
};
|
|
632
|
-
var
|
|
649
|
+
var KIND_SYMBOLS = [
|
|
633
650
|
["It6", "italian"],
|
|
634
651
|
["Fr6", "french"],
|
|
635
652
|
["Ger6", "german"],
|
|
636
653
|
// The German sixth's figures over its bass are 6/5; both spellings are in use.
|
|
637
654
|
["Ger65", "german"]
|
|
638
|
-
]
|
|
655
|
+
];
|
|
656
|
+
var KIND_BY_SYMBOL = new Map(KIND_SYMBOLS);
|
|
639
657
|
var SYMBOL_BY_KIND = {
|
|
640
658
|
italian: "It6",
|
|
641
659
|
french: "Fr6",
|
|
642
660
|
german: "Ger6"
|
|
643
661
|
};
|
|
644
662
|
function bassPcOf(key) {
|
|
645
|
-
return
|
|
663
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc + BASS_ABOVE_TONIC);
|
|
646
664
|
}
|
|
647
665
|
function bareSpelling(note) {
|
|
648
666
|
return { letter: note.letter, alter: note.alter };
|
|
@@ -656,72 +674,74 @@ function augmentedSixthChord(kind, key) {
|
|
|
656
674
|
return augmentedSixthOn(kind, key);
|
|
657
675
|
}
|
|
658
676
|
function augmentedSixthOn(kind, keyLike) {
|
|
659
|
-
const checked =
|
|
677
|
+
const checked = _chunkS3QELJUEcjs.assertOneOf.call(void 0, kind, KINDS, "augmented sixth kind");
|
|
660
678
|
const shape = CHORD_SHAPE[checked];
|
|
661
|
-
const { scale: key, tonic } =
|
|
679
|
+
const { scale: key, tonic } = _chunkYDGMWH43cjs.resolveKey.call(void 0, keyLike);
|
|
662
680
|
const bassPc = bassPcOf(key);
|
|
663
|
-
const
|
|
664
|
-
chord.intervals = [...shape.intervals];
|
|
665
|
-
const bass = _chunkS5BKZZGMcjs.transposeByInterval.call(void 0, tonic, BASS_INTERVAL);
|
|
681
|
+
const bass = _chunkS3QELJUEcjs.transposeByInterval.call(void 0, tonic, BASS_INTERVAL);
|
|
666
682
|
const tones = spelledInChordOrder(checked, tonic);
|
|
667
683
|
const [root = bass] = tones;
|
|
668
|
-
chord
|
|
669
|
-
|
|
670
|
-
|
|
684
|
+
const chord = _chunkYDGMWH43cjs.makeSpelledChord.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, bassPc + shape.rootAboveBass), shape.quality, {
|
|
685
|
+
bassPc,
|
|
686
|
+
rootSpelling: bareSpelling(root),
|
|
687
|
+
bassSpelling: bareSpelling(bass),
|
|
688
|
+
toneSpellings: tones.map(bareSpelling)
|
|
689
|
+
});
|
|
690
|
+
chord.intervals = [...shape.intervals];
|
|
671
691
|
return chord;
|
|
672
692
|
}
|
|
673
693
|
function kindOfPitchClasses(pcs, bass) {
|
|
674
694
|
for (const kind of KINDS) {
|
|
675
695
|
const tones = TONES_ABOVE_BASS[kind];
|
|
676
|
-
if (pcs.size === tones.length && tones.every((tone) => pcs.has(
|
|
696
|
+
if (pcs.size === tones.length && tones.every((tone) => pcs.has(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, bass + tone)))) {
|
|
677
697
|
return kind;
|
|
678
698
|
}
|
|
679
699
|
}
|
|
680
700
|
return null;
|
|
681
701
|
}
|
|
682
702
|
function spellingId(note) {
|
|
683
|
-
return `${
|
|
703
|
+
return `${_chunkS3QELJUEcjs.diatonicLetterOf.call(void 0, note.letter)}:${note.alter}`;
|
|
684
704
|
}
|
|
685
705
|
function spellsAugmentedSixth(chord, kind, key) {
|
|
686
706
|
const tonic = key.tonic;
|
|
687
|
-
const written = new Set(
|
|
707
|
+
const written = new Set(_chunkYDGMWH43cjs.spellChord.call(void 0, chord, tonic, key.scale).map(spellingId));
|
|
688
708
|
const tones = spelledFromTonic(kind, tonic).map(spellingId);
|
|
689
709
|
return written.size === tones.length && tones.every((tone) => written.has(tone));
|
|
690
710
|
}
|
|
691
711
|
function augmentedSixthKind(chord, key) {
|
|
692
|
-
return augmentedSixthKindOf(
|
|
712
|
+
return augmentedSixthKindOf(_chunkYDGMWH43cjs.toChordData.call(void 0, chord), key);
|
|
693
713
|
}
|
|
694
714
|
function augmentedSixthKindOf(chord, keyLike) {
|
|
695
|
-
const resolved =
|
|
715
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, keyLike);
|
|
696
716
|
const bass = bassPcOf(resolved.scale);
|
|
697
|
-
if (
|
|
717
|
+
if (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, _nullishCoalesce(chord.bassPc, () => ( chord.rootPc))) !== bass) {
|
|
698
718
|
return null;
|
|
699
719
|
}
|
|
700
|
-
const kind = kindOfPitchClasses(new Set(
|
|
720
|
+
const kind = kindOfPitchClasses(new Set(_chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord)), bass);
|
|
701
721
|
if (kind === null || !spellsAugmentedSixth(chord, kind, resolved)) {
|
|
702
722
|
return null;
|
|
703
723
|
}
|
|
704
724
|
return kind;
|
|
705
725
|
}
|
|
706
726
|
function augmentedSixthFromPitchClasses(pcs, bassPc, key) {
|
|
707
|
-
return augmentedSixthOverBass(
|
|
727
|
+
return augmentedSixthOverBass(_chunkS3QELJUEcjs.assertArray.call(void 0, pcs, "pcs"), bassPc, key);
|
|
708
728
|
}
|
|
709
729
|
function augmentedSixthOverBass(pcs, bassPc, keyLike) {
|
|
710
|
-
const resolved =
|
|
730
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, keyLike);
|
|
711
731
|
const bass = bassPcOf(resolved.scale);
|
|
712
|
-
if (
|
|
732
|
+
if (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, bassPc) !== bass) {
|
|
713
733
|
return null;
|
|
714
734
|
}
|
|
715
|
-
const kind = kindOfPitchClasses(new Set(pcs.map(
|
|
735
|
+
const kind = kindOfPitchClasses(new Set(pcs.map(_chunkS3QELJUEcjs.pitchClassOf)), bass);
|
|
716
736
|
return kind === null ? null : augmentedSixthOn(kind, resolved);
|
|
717
737
|
}
|
|
718
738
|
function spellAugmentedSixth(kind, tonic) {
|
|
719
|
-
return spelledFromTonic(kind,
|
|
739
|
+
return spelledFromTonic(kind, _chunkS3QELJUEcjs.toNoteData.call(void 0, tonic));
|
|
720
740
|
}
|
|
721
741
|
function spelledFromTonic(kind, tonic) {
|
|
722
|
-
const checked =
|
|
723
|
-
const bass =
|
|
724
|
-
return SPELLED_ABOVE_BASS[checked].map((interval) =>
|
|
742
|
+
const checked = _chunkS3QELJUEcjs.assertOneOf.call(void 0, kind, KINDS, "augmented sixth kind");
|
|
743
|
+
const bass = _chunkS3QELJUEcjs.transposeByInterval.call(void 0, tonic, BASS_INTERVAL);
|
|
744
|
+
return SPELLED_ABOVE_BASS[checked].map((interval) => _chunkS3QELJUEcjs.transposeByInterval.call(void 0, bass, interval));
|
|
725
745
|
}
|
|
726
746
|
function augmentedSixthFromSymbol(symbol, key) {
|
|
727
747
|
const kind = KIND_BY_SYMBOL.get(symbol);
|
|
@@ -737,11 +757,11 @@ var SUBDOMINANT_DEGREE = 4;
|
|
|
737
757
|
var DOMINANT_DEGREE = 5;
|
|
738
758
|
var SUBMEDIANT_DEGREE = 6;
|
|
739
759
|
function degreeOffset(degreeNumber, key) {
|
|
740
|
-
return
|
|
760
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, degreeRootPc(degreeNumber, romanReference(key)) - key.rootPc);
|
|
741
761
|
}
|
|
742
762
|
function thirdBelongsToKey(chord, key) {
|
|
743
763
|
return chord.intervals.some(
|
|
744
|
-
(interval) => (
|
|
764
|
+
(interval) => (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, interval) === 3 || _chunkS3QELJUEcjs.pitchClassOf.call(void 0, interval) === 4) && _chunkYDGMWH43cjs.isScaleTone.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc + interval), key)
|
|
745
765
|
);
|
|
746
766
|
}
|
|
747
767
|
function deceptiveTargets(key) {
|
|
@@ -753,25 +773,25 @@ function deceptiveTargets(key) {
|
|
|
753
773
|
return borrowed === submediant ? [submediant] : [submediant, borrowed];
|
|
754
774
|
}
|
|
755
775
|
function restsOnDominant(to, key) {
|
|
756
|
-
if (
|
|
776
|
+
if (_chunkYDGMWH43cjs.hasMajorThird.call(void 0, to) || _chunkYDGMWH43cjs.isDominantChordOf.call(void 0, to, key)) {
|
|
757
777
|
return true;
|
|
758
778
|
}
|
|
759
|
-
if (
|
|
779
|
+
if (_chunkYDGMWH43cjs.scaleSystemOf.call(void 0, key) !== "modal") {
|
|
760
780
|
return false;
|
|
761
781
|
}
|
|
762
|
-
const dominantPc =
|
|
763
|
-
const leadingToneDominant =
|
|
782
|
+
const dominantPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc + degreeOffset(DOMINANT_DEGREE, key));
|
|
783
|
+
const leadingToneDominant = _chunkYDGMWH43cjs.isScaleTone.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, dominantPc + 4), key);
|
|
764
784
|
return !leadingToneDominant && thirdBelongsToKey(to, key);
|
|
765
785
|
}
|
|
766
786
|
function isTonicSixFour(chord, key) {
|
|
767
|
-
if (
|
|
787
|
+
if (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc) !== 0 || chord.bassPc === void 0) {
|
|
768
788
|
return false;
|
|
769
789
|
}
|
|
770
|
-
const isTriad = chord.intervals.length === 3 && chord.intervals.some((interval) =>
|
|
771
|
-
return isTriad &&
|
|
790
|
+
const isTriad = chord.intervals.length === 3 && chord.intervals.some((interval) => _chunkS3QELJUEcjs.pitchClassOf.call(void 0, interval) === 7);
|
|
791
|
+
return isTriad && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.bassPc - chord.rootPc) === 7;
|
|
772
792
|
}
|
|
773
793
|
function isCadentialSixFour(chord, next, key) {
|
|
774
|
-
return isTonicSixFour(chord, key) &&
|
|
794
|
+
return isTonicSixFour(chord, key) && _chunkYDGMWH43cjs.isDominantChordOf.call(void 0, next, key) && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, _nullishCoalesce(chord.bassPc, () => ( chord.rootPc))) === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, _nullishCoalesce(next.bassPc, () => ( next.rootPc)));
|
|
775
795
|
}
|
|
776
796
|
function outerPitches(voicing) {
|
|
777
797
|
let bass;
|
|
@@ -790,7 +810,7 @@ function outerPitches(voicing) {
|
|
|
790
810
|
return { bass, soprano };
|
|
791
811
|
}
|
|
792
812
|
function bassPcOf2(chord, voicedBass) {
|
|
793
|
-
return
|
|
813
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, _nullishCoalesce(_nullishCoalesce(voicedBass, () => ( chord.bassPc)), () => ( chord.rootPc)));
|
|
794
814
|
}
|
|
795
815
|
var CADENCE_TYPES = Object.freeze([
|
|
796
816
|
"authentic",
|
|
@@ -801,17 +821,17 @@ var CADENCE_TYPES = Object.freeze([
|
|
|
801
821
|
"modal"
|
|
802
822
|
]);
|
|
803
823
|
function cadenceType(from, to, key, fromBassPc, toBassPc) {
|
|
804
|
-
const tonic =
|
|
805
|
-
const fromOffset =
|
|
806
|
-
const toOffset =
|
|
807
|
-
const dominant =
|
|
808
|
-
if ((dominant ||
|
|
824
|
+
const tonic = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
825
|
+
const fromOffset = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, from.rootPc - tonic);
|
|
826
|
+
const toOffset = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, to.rootPc - tonic);
|
|
827
|
+
const dominant = _chunkYDGMWH43cjs.isDominantChordOf.call(void 0, from, key);
|
|
828
|
+
if ((dominant || _chunkYDGMWH43cjs.isLeadingToneChordOf.call(void 0, from, key)) && toOffset === 0) {
|
|
809
829
|
return "authentic";
|
|
810
830
|
}
|
|
811
831
|
if (fromOffset === degreeOffset(SUBDOMINANT_DEGREE, key) && toOffset === 0) {
|
|
812
832
|
return "plagal";
|
|
813
833
|
}
|
|
814
|
-
if (fromOffset === 10 && toOffset === 0 &&
|
|
834
|
+
if (fromOffset === 10 && toOffset === 0 && _chunkYDGMWH43cjs.hasMajorThird.call(void 0, from)) {
|
|
815
835
|
return "modal";
|
|
816
836
|
}
|
|
817
837
|
if (dominant && deceptiveTargets(key).includes(toOffset)) {
|
|
@@ -819,7 +839,7 @@ function cadenceType(from, to, key, fromBassPc, toBassPc) {
|
|
|
819
839
|
}
|
|
820
840
|
const dominantOffset = degreeOffset(DOMINANT_DEGREE, key);
|
|
821
841
|
const half = toOffset === dominantOffset && restsOnDominant(to, key) && fromOffset !== dominantOffset;
|
|
822
|
-
if (half && isMinorScale(key) && fromOffset === 5 &&
|
|
842
|
+
if (half && isMinorScale(key) && fromOffset === 5 && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, fromBassPc - tonic) === 8 && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, toBassPc - tonic) === 7) {
|
|
823
843
|
return "phrygian";
|
|
824
844
|
}
|
|
825
845
|
return half ? "half" : null;
|
|
@@ -921,12 +941,12 @@ function cadenceAlternatives(facts) {
|
|
|
921
941
|
return out;
|
|
922
942
|
}
|
|
923
943
|
function detectCadence(from, to, key, opts = {}) {
|
|
924
|
-
const { approach, ...rest } =
|
|
944
|
+
const { approach, ...rest } = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
925
945
|
return cadenceBetween(
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
approach === void 0 ? rest : { ...rest, approach:
|
|
946
|
+
_chunkYDGMWH43cjs.toChordData.call(void 0, from),
|
|
947
|
+
_chunkYDGMWH43cjs.toChordData.call(void 0, to),
|
|
948
|
+
_chunkYDGMWH43cjs.toKeyScale.call(void 0, key),
|
|
949
|
+
approach === void 0 ? rest : { ...rest, approach: _chunkYDGMWH43cjs.toChordData.call(void 0, approach) }
|
|
930
950
|
);
|
|
931
951
|
}
|
|
932
952
|
function cadenceBetween(from, to, key, opts = {}) {
|
|
@@ -935,11 +955,11 @@ function cadenceBetween(from, to, key, opts = {}) {
|
|
|
935
955
|
const toOuter = outerPitches(_nullishCoalesce(toVoicing, () => ( [])));
|
|
936
956
|
const fromBassPc = bassPcOf2(from, fromOuter.bass);
|
|
937
957
|
const toBassPc = bassPcOf2(to, toOuter.bass);
|
|
938
|
-
const toRootPosition = toBassPc ===
|
|
939
|
-
const rootPosition = fromBassPc ===
|
|
940
|
-
const soprano = toOuter.soprano === void 0 ? null :
|
|
958
|
+
const toRootPosition = toBassPc === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, to.rootPc);
|
|
959
|
+
const rootPosition = fromBassPc === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, from.rootPc) && toRootPosition;
|
|
960
|
+
const soprano = toOuter.soprano === void 0 ? null : _chunkYDGMWH43cjs.chordToneRole.call(void 0, toOuter.soprano, to);
|
|
941
961
|
const type = cadenceType(from, to, key, fromBassPc, toBassPc);
|
|
942
|
-
const leadingTone =
|
|
962
|
+
const leadingTone = _chunkYDGMWH43cjs.isLeadingToneChordOf.call(void 0, from, key);
|
|
943
963
|
const facts = {
|
|
944
964
|
type,
|
|
945
965
|
strength: type === "authentic" ? authenticStrength(leadingTone, rootPosition, toOuter.soprano !== void 0, soprano) : null,
|
|
@@ -948,10 +968,10 @@ function cadenceBetween(from, to, key, opts = {}) {
|
|
|
948
968
|
// promised is the one it does not get.
|
|
949
969
|
evaded: type === "authentic" && !toRootPosition,
|
|
950
970
|
leadingTone,
|
|
951
|
-
fromOffset:
|
|
952
|
-
toOffset:
|
|
971
|
+
fromOffset: _chunkS3QELJUEcjs.pitchClassOf.call(void 0, from.rootPc - key.rootPc),
|
|
972
|
+
toOffset: _chunkS3QELJUEcjs.pitchClassOf.call(void 0, to.rootPc - key.rootPc),
|
|
953
973
|
minor: isMinorScale(key),
|
|
954
|
-
onFifthDegree:
|
|
974
|
+
onFifthDegree: _chunkS3QELJUEcjs.pitchClassOf.call(void 0, to.rootPc - key.rootPc) === degreeOffset(DOMINANT_DEGREE, key),
|
|
955
975
|
sixFour: opts.approach !== void 0 && isCadentialSixFour(opts.approach, from, key),
|
|
956
976
|
withinSixFour: isCadentialSixFour(from, to, key)
|
|
957
977
|
};
|
|
@@ -972,53 +992,45 @@ function cadenceBetween(from, to, key, opts = {}) {
|
|
|
972
992
|
// src/analyze/functional/borrowed.ts
|
|
973
993
|
function isMinorScaleAlteration(chord, key) {
|
|
974
994
|
if (!isMinorScale(key)) return false;
|
|
975
|
-
const alteredKey = { rootPc:
|
|
976
|
-
if (
|
|
977
|
-
return
|
|
995
|
+
const alteredKey = { rootPc: _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunkYDGMWH43cjs.HARMONIC_MINOR_MASK };
|
|
996
|
+
if (_chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, alteredKey)) return true;
|
|
997
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc) === 11 && _chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, { rootPc: _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunkYDGMWH43cjs.MELODIC_MINOR_MASK });
|
|
978
998
|
}
|
|
979
999
|
function isBorrowed(chord, key) {
|
|
980
|
-
if (
|
|
1000
|
+
if (_chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, key)) {
|
|
981
1001
|
return false;
|
|
982
1002
|
}
|
|
983
|
-
if (
|
|
1003
|
+
if (_chunkYDGMWH43cjs.isNeapolitanChordOf.call(void 0, chord, key)) {
|
|
984
1004
|
return true;
|
|
985
1005
|
}
|
|
986
1006
|
if (isMinorScaleAlteration(chord, key)) {
|
|
987
1007
|
return false;
|
|
988
1008
|
}
|
|
989
|
-
return
|
|
1009
|
+
return _chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, parallelScale(key));
|
|
990
1010
|
}
|
|
991
1011
|
function borrowedSourceOf(chord, key) {
|
|
992
|
-
if (
|
|
1012
|
+
if (_chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, key)) {
|
|
993
1013
|
return null;
|
|
994
1014
|
}
|
|
995
|
-
if (
|
|
1015
|
+
if (_chunkYDGMWH43cjs.isNeapolitanChordOf.call(void 0, chord, key)) return "neapolitan";
|
|
996
1016
|
if (isBorrowed(chord, key)) {
|
|
997
1017
|
return isMinorScale(key) ? "parallelMajor" : "parallelMinor";
|
|
998
1018
|
}
|
|
999
1019
|
return null;
|
|
1000
1020
|
}
|
|
1001
1021
|
function isBorrowedChord(chord, key) {
|
|
1002
|
-
return isBorrowed(
|
|
1022
|
+
return isBorrowed(_chunkYDGMWH43cjs.toChordData.call(void 0, chord), _chunkYDGMWH43cjs.toKeyScale.call(void 0, key));
|
|
1003
1023
|
}
|
|
1004
1024
|
function borrowedSource(chord, key) {
|
|
1005
|
-
return borrowedSourceOf(
|
|
1025
|
+
return borrowedSourceOf(_chunkYDGMWH43cjs.toChordData.call(void 0, chord), _chunkYDGMWH43cjs.toKeyScale.call(void 0, key));
|
|
1006
1026
|
}
|
|
1007
1027
|
|
|
1008
1028
|
// src/analyze/functional/tonicization.ts
|
|
1009
1029
|
function isTonicizableRoot(rootPc, key) {
|
|
1010
|
-
return
|
|
1011
|
-
}
|
|
1012
|
-
function appliedTarget(chord, key) {
|
|
1013
|
-
const dominant = _chunk3R3QVKY5cjs.hasDominantSonority.call(void 0, chord);
|
|
1014
|
-
const leadingTone = _chunk3R3QVKY5cjs.LEADING_TONE_QUALITIES.has(chord.quality);
|
|
1015
|
-
if (!dominant && !leadingTone) {
|
|
1016
|
-
return null;
|
|
1017
|
-
}
|
|
1018
|
-
return _chunk3R3QVKY5cjs.appliedDominantTarget.call(void 0, chord.rootPc + (dominant ? 5 : 1), key);
|
|
1030
|
+
return _chunkYDGMWH43cjs.tonicizableDegrees.call(void 0, key).some((degree) => degree.rootPc === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc));
|
|
1019
1031
|
}
|
|
1020
1032
|
function isAppliedDominant(chord, key) {
|
|
1021
|
-
if (
|
|
1033
|
+
if (_chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, key)) {
|
|
1022
1034
|
return false;
|
|
1023
1035
|
}
|
|
1024
1036
|
const source = borrowedSourceOf(chord, key);
|
|
@@ -1028,10 +1040,10 @@ function isAppliedDominant(chord, key) {
|
|
|
1028
1040
|
return pointsAtTonicizableDegree(chord, key);
|
|
1029
1041
|
}
|
|
1030
1042
|
function pointsAtTonicizableDegree(chord, key) {
|
|
1031
|
-
if (
|
|
1043
|
+
if (_chunkYDGMWH43cjs.appliedChordTarget.call(void 0, chord, key) !== null) {
|
|
1032
1044
|
return true;
|
|
1033
1045
|
}
|
|
1034
|
-
return
|
|
1046
|
+
return _chunkYDGMWH43cjs.soundsDominantSeventh.call(void 0, chord) && isTonicizableRoot(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc - 1), key);
|
|
1035
1047
|
}
|
|
1036
1048
|
|
|
1037
1049
|
// src/analyze/functional/roman.ts
|
|
@@ -1071,7 +1083,8 @@ function seventhQuality(base, halfDim) {
|
|
|
1071
1083
|
}
|
|
1072
1084
|
return base === "maj" ? "dom7" : "min7";
|
|
1073
1085
|
}
|
|
1074
|
-
var
|
|
1086
|
+
var INVERSION_FIGURE_LIST = ["6", "64", "65", "43", "42", "2", "7"];
|
|
1087
|
+
var INVERSION_FIGURES = new Set(INVERSION_FIGURE_LIST);
|
|
1075
1088
|
var ROMAN_STYLE = {
|
|
1076
1089
|
maj: { lower: false, suffix: "" },
|
|
1077
1090
|
min: { lower: true, suffix: "" },
|
|
@@ -1143,36 +1156,50 @@ function parseInversion(figures) {
|
|
|
1143
1156
|
}
|
|
1144
1157
|
return { inversion: 0, seventh: false };
|
|
1145
1158
|
}
|
|
1146
|
-
function
|
|
1159
|
+
function numeralRootSpelling(tonic, degreeNumber, rootPc) {
|
|
1160
|
+
const spelling = _chunkYDGMWH43cjs.spellingAbove.call(void 0, tonic, degreeNumber - 1, rootPc);
|
|
1161
|
+
return Math.abs(spelling.alter) <= 2 ? spelling : void 0;
|
|
1162
|
+
}
|
|
1163
|
+
function parseSimpleRoman(text, resolved) {
|
|
1164
|
+
const key = resolved.scale;
|
|
1147
1165
|
const match = /^([b#]?)([iIvV]+)(.*)$/.exec(text.trim());
|
|
1148
1166
|
if (!match) {
|
|
1149
|
-
throw new (0,
|
|
1167
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`Invalid Roman numeral: ${text}`);
|
|
1150
1168
|
}
|
|
1151
1169
|
const glyphText = _nullishCoalesce(match[2], () => ( ""));
|
|
1152
1170
|
if (glyphText !== glyphText.toUpperCase() && glyphText !== glyphText.toLowerCase()) {
|
|
1153
|
-
throw new (0,
|
|
1171
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`Roman numeral must use one case: ${text}`);
|
|
1154
1172
|
}
|
|
1155
1173
|
const accidental = match[1] === "b" ? -1 : match[1] === "#" ? 1 : 0;
|
|
1156
1174
|
const glyph = glyphText.toUpperCase();
|
|
1157
1175
|
const degreeNumber = ROMAN_TO_DEGREE[glyph];
|
|
1158
1176
|
if (degreeNumber === void 0) {
|
|
1159
|
-
throw new (0,
|
|
1177
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`Invalid Roman numeral: ${text}`);
|
|
1160
1178
|
}
|
|
1161
1179
|
const isUpper = glyphText[0] === _optionalChain([glyphText, 'access', _5 => _5[0], 'optionalAccess', _6 => _6.toUpperCase, 'call', _7 => _7()]);
|
|
1162
1180
|
const suffix = _nullishCoalesce(match[3], () => ( ""));
|
|
1163
1181
|
const frame = romanReference(key);
|
|
1164
1182
|
const redundantFlat = accidental === -1 && loweredDegrees(frame).has(degreeNumber);
|
|
1165
|
-
const diatonicRootPc =
|
|
1183
|
+
const diatonicRootPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0,
|
|
1166
1184
|
degreeRootPc(degreeNumber, frame) + (redundantFlat ? 0 : accidental)
|
|
1167
1185
|
);
|
|
1168
|
-
const rootForQuality = (quality2) => accidental === 0 && degreeNumber === 7 && loweredDegrees(frame).has(7) &&
|
|
1186
|
+
const rootForQuality = (quality2) => accidental === 0 && degreeNumber === 7 && loweredDegrees(frame).has(7) && _chunkYDGMWH43cjs.LEADING_TONE_QUALITIES.has(quality2) ? _chunkS3QELJUEcjs.pitchClassOf.call(void 0, diatonicRootPc + 1) : diatonicRootPc;
|
|
1169
1187
|
const canonical = SUFFIX_QUALITY.get(`${isUpper ? "u" : "l"}:${suffix}`);
|
|
1188
|
+
const parsed = (quality2, inversion2) => {
|
|
1189
|
+
const rootPc = rootForQuality(quality2);
|
|
1190
|
+
return {
|
|
1191
|
+
rootPc,
|
|
1192
|
+
rootSpelling: numeralRootSpelling(resolved.tonic, degreeNumber, rootPc),
|
|
1193
|
+
quality: quality2,
|
|
1194
|
+
inversion: inversion2
|
|
1195
|
+
};
|
|
1196
|
+
};
|
|
1170
1197
|
if (canonical !== void 0) {
|
|
1171
|
-
return
|
|
1198
|
+
return parsed(canonical, 0);
|
|
1172
1199
|
}
|
|
1173
1200
|
const parsedSuffix = /^(o|°|dim|ø|\+|aug)?(maj7|M7)?(65|64|43|42|7|6|2)?$/.exec(suffix);
|
|
1174
1201
|
if (!parsedSuffix) {
|
|
1175
|
-
throw new (0,
|
|
1202
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`Unsupported suffix "${suffix}" in Roman numeral: ${text}`);
|
|
1176
1203
|
}
|
|
1177
1204
|
const qualityMarker = _nullishCoalesce(parsedSuffix[1], () => ( ""));
|
|
1178
1205
|
const isDim = qualityMarker === "o" || qualityMarker === "\xB0" || qualityMarker === "dim";
|
|
@@ -1181,7 +1208,7 @@ function parseSimpleRoman(text, key) {
|
|
|
1181
1208
|
const explicitMaj7 = parsedSuffix[2] !== void 0;
|
|
1182
1209
|
const figures = _nullishCoalesce(parsedSuffix[3], () => ( ""));
|
|
1183
1210
|
if (figures !== "" && !INVERSION_FIGURES.has(figures)) {
|
|
1184
|
-
throw new (0,
|
|
1211
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
1185
1212
|
`Unsupported figured-bass or extension "${figures}" in Roman numeral: ${text}`
|
|
1186
1213
|
);
|
|
1187
1214
|
}
|
|
@@ -1207,27 +1234,30 @@ function parseSimpleRoman(text, key) {
|
|
|
1207
1234
|
} else {
|
|
1208
1235
|
quality = base;
|
|
1209
1236
|
}
|
|
1210
|
-
return
|
|
1237
|
+
return parsed(quality, inversion);
|
|
1211
1238
|
}
|
|
1212
1239
|
var NEAPOLITAN_SIXTH = "N6";
|
|
1213
1240
|
function chromaticSymbolChord(text, key) {
|
|
1214
1241
|
if (text === NEAPOLITAN_SIXTH) {
|
|
1215
|
-
const rootPc =
|
|
1216
|
-
return
|
|
1242
|
+
const rootPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.scale.rootPc + 1);
|
|
1243
|
+
return _chunkYDGMWH43cjs.makeSpelledChord.call(void 0, rootPc, "maj", {
|
|
1244
|
+
bassPc: _chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc + 4),
|
|
1245
|
+
rootSpelling: numeralRootSpelling(key.tonic, 2, rootPc)
|
|
1246
|
+
});
|
|
1217
1247
|
}
|
|
1218
1248
|
return augmentedSixthFromSymbol(text, key);
|
|
1219
1249
|
}
|
|
1220
|
-
function tonicizedKey(targetRoot, key) {
|
|
1221
|
-
return
|
|
1222
|
-
scale:
|
|
1223
|
-
tonic:
|
|
1250
|
+
function tonicizedKey(targetRoot, key, written) {
|
|
1251
|
+
return _chunkYDGMWH43cjs.resolveKey.call(void 0, {
|
|
1252
|
+
scale: _chunkYDGMWH43cjs.majorKey.call(void 0, targetRoot),
|
|
1253
|
+
tonic: _nullishCoalesce(written, () => ( _chunkYDGMWH43cjs.spellPitchClass.call(void 0, targetRoot, key.tonic, key.scale)))
|
|
1224
1254
|
});
|
|
1225
1255
|
}
|
|
1226
1256
|
function augmentedSixthTarget(chord, key) {
|
|
1227
|
-
if (
|
|
1257
|
+
if (_chunkYDGMWH43cjs.chordToneSpellings.call(void 0, chord) === void 0) {
|
|
1228
1258
|
return null;
|
|
1229
1259
|
}
|
|
1230
|
-
for (const degree of
|
|
1260
|
+
for (const degree of _chunkYDGMWH43cjs.tonicizableDegrees.call(void 0, key.scale)) {
|
|
1231
1261
|
if (degree.degreeNumber === 1) {
|
|
1232
1262
|
continue;
|
|
1233
1263
|
}
|
|
@@ -1238,60 +1268,64 @@ function augmentedSixthTarget(chord, key) {
|
|
|
1238
1268
|
return null;
|
|
1239
1269
|
}
|
|
1240
1270
|
function chordFromParsed(parsed) {
|
|
1241
|
-
const
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1271
|
+
const bassInterval = parsed.inversion > 0 ? _chunkYDGMWH43cjs.QUALITY_INTERVALS[parsed.quality][parsed.inversion] : void 0;
|
|
1272
|
+
return _chunkYDGMWH43cjs.makeSpelledChord.call(void 0, parsed.rootPc, parsed.quality, {
|
|
1273
|
+
bassPc: bassInterval === void 0 ? void 0 : _chunkS3QELJUEcjs.pitchClassOf.call(void 0, parsed.rootPc + bassInterval),
|
|
1274
|
+
rootSpelling: parsed.rootSpelling
|
|
1275
|
+
});
|
|
1246
1276
|
}
|
|
1247
1277
|
function romanToChord(text, key) {
|
|
1248
|
-
const resolved =
|
|
1249
|
-
|
|
1278
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, key);
|
|
1279
|
+
if (typeof text !== "string") {
|
|
1280
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
1281
|
+
`Roman numeral must be a string; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, text)}`
|
|
1282
|
+
);
|
|
1283
|
+
}
|
|
1250
1284
|
const trimmed = text.trim().replace(/(\d)\/(?=\d)/g, "$1");
|
|
1251
1285
|
const slash = trimmed.indexOf("/");
|
|
1252
1286
|
if (slash >= 0) {
|
|
1253
1287
|
const applied = trimmed.slice(0, slash);
|
|
1254
1288
|
const target = trimmed.slice(slash + 1);
|
|
1255
|
-
const
|
|
1256
|
-
const localKey = tonicizedKey(
|
|
1257
|
-
return _nullishCoalesce(chromaticSymbolChord(applied, localKey), () => ( chordFromParsed(parseSimpleRoman(applied, localKey
|
|
1289
|
+
const targetNumeral = parseSimpleRoman(target, resolved);
|
|
1290
|
+
const localKey = tonicizedKey(targetNumeral.rootPc, resolved, targetNumeral.rootSpelling);
|
|
1291
|
+
return _nullishCoalesce(chromaticSymbolChord(applied, localKey), () => ( chordFromParsed(parseSimpleRoman(applied, localKey))));
|
|
1258
1292
|
}
|
|
1259
|
-
return _nullishCoalesce(chromaticSymbolChord(trimmed, resolved), () => ( chordFromParsed(parseSimpleRoman(trimmed,
|
|
1293
|
+
return _nullishCoalesce(chromaticSymbolChord(trimmed, resolved), () => ( chordFromParsed(parseSimpleRoman(trimmed, resolved))));
|
|
1260
1294
|
}
|
|
1261
1295
|
function romanStyle(quality) {
|
|
1262
1296
|
return ROMAN_STYLE[quality];
|
|
1263
1297
|
}
|
|
1264
|
-
function romanSpelling(rootPc, key) {
|
|
1265
|
-
const tones =
|
|
1266
|
-
const diatonic = tones.indexOf(
|
|
1298
|
+
function romanSpelling(rootPc, key, quality) {
|
|
1299
|
+
const tones = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, romanReference(key));
|
|
1300
|
+
const diatonic = tones.indexOf(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc));
|
|
1267
1301
|
if (diatonic >= 0) {
|
|
1268
1302
|
return { degreeNumber: diatonic + 1, accidental: "" };
|
|
1269
1303
|
}
|
|
1270
1304
|
const lowered = loweredDegrees(romanReference(key));
|
|
1271
1305
|
for (let i = 0; i < tones.length; i += 1) {
|
|
1272
|
-
if (lowered.has(i + 1) &&
|
|
1306
|
+
if (lowered.has(i + 1) && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) + 1) === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
1273
1307
|
return { degreeNumber: i + 1, accidental: "#" };
|
|
1274
1308
|
}
|
|
1275
1309
|
}
|
|
1276
|
-
for (let i = 0; i < tones.length; i += 1) {
|
|
1310
|
+
for (let i = 0; i < tones.length && !_chunkYDGMWH43cjs.LEADING_TONE_QUALITIES.has(quality); i += 1) {
|
|
1277
1311
|
const degreeNumber2 = i + 1;
|
|
1278
1312
|
if (degreeNumber2 === 1 || degreeNumber2 === 5) {
|
|
1279
1313
|
continue;
|
|
1280
1314
|
}
|
|
1281
|
-
if (
|
|
1315
|
+
if (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) - 1) === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
1282
1316
|
return { degreeNumber: degreeNumber2, accidental: "b" };
|
|
1283
1317
|
}
|
|
1284
1318
|
}
|
|
1285
1319
|
for (let i = 0; i < tones.length; i += 1) {
|
|
1286
|
-
if (
|
|
1320
|
+
if (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) + 1) === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
1287
1321
|
return { degreeNumber: i + 1, accidental: "#" };
|
|
1288
1322
|
}
|
|
1289
1323
|
}
|
|
1290
|
-
const [degreeNumber, accidental] = _nullishCoalesce(OFFSET_SPELLING[
|
|
1324
|
+
const [degreeNumber, accidental] = _nullishCoalesce(OFFSET_SPELLING[_chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc - key.rootPc)], () => ( [1, ""]));
|
|
1291
1325
|
return { degreeNumber, accidental };
|
|
1292
1326
|
}
|
|
1293
1327
|
function seventhDegreeAccidental(accidental, degreeNumber, quality, key) {
|
|
1294
|
-
if (degreeNumber !== 7 || !
|
|
1328
|
+
if (degreeNumber !== 7 || !_chunkYDGMWH43cjs.LEADING_TONE_QUALITIES.has(quality) || !loweredDegrees(romanReference(key)).has(7)) {
|
|
1295
1329
|
return accidental;
|
|
1296
1330
|
}
|
|
1297
1331
|
if (accidental === "#") {
|
|
@@ -1319,8 +1353,9 @@ function baseMarker(quality) {
|
|
|
1319
1353
|
}
|
|
1320
1354
|
var TRIAD_FIGURES = { 1: "6", 2: "64" };
|
|
1321
1355
|
var SEVENTH_FIGURES = { 1: "65", 2: "43", 3: "42" };
|
|
1322
|
-
var
|
|
1323
|
-
var
|
|
1356
|
+
var TRIAD_FIGURE_QUALITY_NAMES = ["maj", "min", "dim", "aug"];
|
|
1357
|
+
var TRIAD_FIGURE_QUALITIES = new Set(TRIAD_FIGURE_QUALITY_NAMES);
|
|
1358
|
+
var SEVENTH_FIGURE_QUALITY_NAMES = [
|
|
1324
1359
|
"maj7",
|
|
1325
1360
|
"min7",
|
|
1326
1361
|
"dom7",
|
|
@@ -1329,50 +1364,90 @@ var SEVENTH_FIGURE_QUALITIES = /* @__PURE__ */ new Set([
|
|
|
1329
1364
|
"minMaj7",
|
|
1330
1365
|
"aug7",
|
|
1331
1366
|
"augMaj7"
|
|
1332
|
-
]
|
|
1367
|
+
];
|
|
1368
|
+
var SEVENTH_FIGURE_QUALITIES = new Set(SEVENTH_FIGURE_QUALITY_NAMES);
|
|
1333
1369
|
function numeralFor(degreeNumber, lower) {
|
|
1334
1370
|
const glyph = ROMAN[degreeNumber - 1];
|
|
1335
1371
|
if (glyph === void 0) {
|
|
1336
|
-
throw new (0,
|
|
1372
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`no Roman numeral for scale degree ${degreeNumber}`);
|
|
1337
1373
|
}
|
|
1338
1374
|
return lower ? glyph.toLowerCase() : glyph;
|
|
1339
1375
|
}
|
|
1340
1376
|
function chordToRoman(chord, key, opts = {}) {
|
|
1341
|
-
return renderRoman(
|
|
1377
|
+
return renderRoman(_chunkYDGMWH43cjs.toChordData.call(void 0, chord), key, _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts")).roman;
|
|
1378
|
+
}
|
|
1379
|
+
function readNumeral(chord, resolved, applied) {
|
|
1380
|
+
const key = resolved.scale;
|
|
1381
|
+
const written = writtenRoot(chord);
|
|
1382
|
+
if (applied) {
|
|
1383
|
+
const target = _nullishCoalesce(augmentedSixthTarget(chord, resolved), () => ( (isAppliedDominant(chord, key) ? _chunkYDGMWH43cjs.appliedChordTarget.call(void 0, chord, key) : null)));
|
|
1384
|
+
if (target !== null && leadsByLetter(chord, written, target, resolved)) {
|
|
1385
|
+
return { kind: "applied", target };
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
return {
|
|
1389
|
+
kind: "root",
|
|
1390
|
+
..._nullishCoalesce(writtenSpelling(chord.rootPc, written, resolved), () => ( romanSpelling(chord.rootPc, key, chord.quality)))
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
function writtenRoot(chord) {
|
|
1394
|
+
const hint = chord.rootSpelling;
|
|
1395
|
+
if (typeof hint !== "object" || hint === null || !Number.isInteger(hint.letter) || hint.letter < 0 || hint.letter > 6 || !Number.isInteger(hint.alter) || _chunkS3QELJUEcjs.pitchClassOf.call(void 0, _chunkS3QELJUEcjs.naturalPitchClassOf.call(void 0, hint.letter) + hint.alter) !== _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc)) {
|
|
1396
|
+
return void 0;
|
|
1397
|
+
}
|
|
1398
|
+
return hint;
|
|
1399
|
+
}
|
|
1400
|
+
function writtenSpelling(rootPc, written, resolved) {
|
|
1401
|
+
const tones = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, romanReference(resolved.scale));
|
|
1402
|
+
if (written === void 0 || tones.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc))) {
|
|
1403
|
+
return void 0;
|
|
1404
|
+
}
|
|
1405
|
+
const degreeNumber = _chunkS3QELJUEcjs.diatonicLetterOf.call(void 0, written.letter - resolved.tonic.letter) + 1;
|
|
1406
|
+
const degreePc = tones[degreeNumber - 1];
|
|
1407
|
+
if (degreePc === void 0) {
|
|
1408
|
+
return void 0;
|
|
1409
|
+
}
|
|
1410
|
+
const offset = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc - degreePc + 6) - 6;
|
|
1411
|
+
return Math.abs(offset) > 1 ? void 0 : { degreeNumber, accidental: offset < 0 ? "b" : offset > 0 ? "#" : "" };
|
|
1412
|
+
}
|
|
1413
|
+
function leadsByLetter(chord, written, target, resolved) {
|
|
1414
|
+
if (written === void 0 || !_chunkYDGMWH43cjs.LEADING_TONE_QUALITIES.has(chord.quality)) {
|
|
1415
|
+
return true;
|
|
1416
|
+
}
|
|
1417
|
+
const targetLetter = _chunkYDGMWH43cjs.spellPitchClass.call(void 0, target.rootPc, resolved.tonic, resolved.scale).letter;
|
|
1418
|
+
return _chunkS3QELJUEcjs.diatonicLetterOf.call(void 0, targetLetter - written.letter) === 1;
|
|
1342
1419
|
}
|
|
1343
1420
|
function renderRoman(chord, keyLike, opts) {
|
|
1344
|
-
const resolved =
|
|
1421
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, keyLike);
|
|
1345
1422
|
const key = resolved.scale;
|
|
1346
1423
|
const augmented = augmentedSixthSymbol(chord, resolved);
|
|
1347
1424
|
if (augmented !== null) {
|
|
1348
1425
|
return { roman: augmented, derivation: { kind: "augmentedSixth" } };
|
|
1349
1426
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
};
|
|
1359
|
-
}
|
|
1427
|
+
const reading = readNumeral(chord, resolved, opts.applied === true);
|
|
1428
|
+
if (reading.kind === "applied") {
|
|
1429
|
+
const local = renderRoman(chord, tonicizedKey(reading.target.rootPc, resolved), {}).roman;
|
|
1430
|
+
const numeral = numeralFor(reading.target.degreeNumber, reading.target.lower);
|
|
1431
|
+
return {
|
|
1432
|
+
roman: `${local}/${numeral}`,
|
|
1433
|
+
derivation: { kind: "applied", target: numeral }
|
|
1434
|
+
};
|
|
1360
1435
|
}
|
|
1361
|
-
const { degreeNumber, accidental: spelledAccidental } =
|
|
1436
|
+
const { degreeNumber, accidental: spelledAccidental } = reading;
|
|
1362
1437
|
const { lower, suffix } = romanStyle(chord.quality);
|
|
1363
1438
|
const cased = numeralFor(degreeNumber, lower);
|
|
1364
1439
|
const accidental = seventhDegreeAccidental(spelledAccidental, degreeNumber, chord.quality, key);
|
|
1365
1440
|
let inversion = 0;
|
|
1366
1441
|
let bass = "root";
|
|
1367
1442
|
if (chord.bassPc !== void 0) {
|
|
1368
|
-
const idx = chord.intervals.findIndex((iv) =>
|
|
1443
|
+
const idx = chord.intervals.findIndex((iv) => _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc + iv) === chord.bassPc);
|
|
1369
1444
|
if (idx > 0) {
|
|
1370
1445
|
inversion = idx;
|
|
1371
1446
|
} else if (idx < 0) {
|
|
1372
1447
|
bass = "foreign";
|
|
1373
1448
|
}
|
|
1374
1449
|
}
|
|
1375
|
-
if (opts.neapolitan === true && inversion === 1 &&
|
|
1450
|
+
if (opts.neapolitan === true && inversion === 1 && _chunkYDGMWH43cjs.isNeapolitanChordOf.call(void 0, chord, key)) {
|
|
1376
1451
|
return { roman: NEAPOLITAN_SIXTH, derivation: { kind: "neapolitan" } };
|
|
1377
1452
|
}
|
|
1378
1453
|
if (inversion > 0) {
|
|
@@ -1405,7 +1480,15 @@ function renderRoman(chord, keyLike, opts) {
|
|
|
1405
1480
|
}
|
|
1406
1481
|
};
|
|
1407
1482
|
}
|
|
1408
|
-
var DEGREE_NAMES = [
|
|
1483
|
+
var DEGREE_NAMES = [
|
|
1484
|
+
"first",
|
|
1485
|
+
"second",
|
|
1486
|
+
"third",
|
|
1487
|
+
"fourth",
|
|
1488
|
+
"fifth",
|
|
1489
|
+
"sixth",
|
|
1490
|
+
"seventh"
|
|
1491
|
+
];
|
|
1409
1492
|
function describeDegree(degreeNumber, accidental, literal) {
|
|
1410
1493
|
const name = _nullishCoalesce(DEGREE_NAMES[degreeNumber - 1], () => ( `${degreeNumber}th`));
|
|
1411
1494
|
if (accidental !== literal) {
|
|
@@ -1471,8 +1554,8 @@ function romanAlternatives(chord, key, opts) {
|
|
|
1471
1554
|
return out;
|
|
1472
1555
|
}
|
|
1473
1556
|
function explainRoman(chord, key, opts = {}) {
|
|
1474
|
-
const asked =
|
|
1475
|
-
const data =
|
|
1557
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
1558
|
+
const data = _chunkYDGMWH43cjs.toChordData.call(void 0, chord);
|
|
1476
1559
|
const { roman, derivation } = renderRoman(data, key, asked);
|
|
1477
1560
|
return {
|
|
1478
1561
|
roman,
|
|
@@ -1541,27 +1624,28 @@ var MINOR_FUNCTION_BY_OFFSET = [
|
|
|
1541
1624
|
// 11 viio
|
|
1542
1625
|
];
|
|
1543
1626
|
function isMinorKey(key) {
|
|
1544
|
-
return isMinorScale(
|
|
1627
|
+
return isMinorScale(_chunkYDGMWH43cjs.toKeyScale.call(void 0, key));
|
|
1545
1628
|
}
|
|
1546
1629
|
function functionOf(chord, key) {
|
|
1547
|
-
return functionWithReason(
|
|
1630
|
+
return functionWithReason(_chunkYDGMWH43cjs.toChordData.call(void 0, chord), _chunkYDGMWH43cjs.resolveKey.call(void 0, key)).function;
|
|
1548
1631
|
}
|
|
1549
1632
|
function degreeFunction(chord, key) {
|
|
1550
1633
|
const functions = isMinorScale(key) ? MINOR_FUNCTION_BY_OFFSET : FUNCTION_BY_OFFSET;
|
|
1551
|
-
return _nullishCoalesce(functions[
|
|
1634
|
+
return _nullishCoalesce(functions[_chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc)], () => ( "tonic"));
|
|
1552
1635
|
}
|
|
1553
|
-
function functionWithReason(chord,
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1636
|
+
function functionWithReason(chord, resolved) {
|
|
1637
|
+
const key = resolved.scale;
|
|
1638
|
+
const offset = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc);
|
|
1639
|
+
if (_chunkYDGMWH43cjs.isNeapolitanChordOf.call(void 0, chord, key)) {
|
|
1556
1640
|
return { function: "subdominant", reason: "neapolitan" };
|
|
1557
1641
|
}
|
|
1558
|
-
if (augmentedSixthKindOf(chord,
|
|
1642
|
+
if (augmentedSixthKindOf(chord, resolved) !== null) {
|
|
1559
1643
|
return { function: "subdominant", reason: "augmentedSixth" };
|
|
1560
1644
|
}
|
|
1561
1645
|
if (isAppliedDominant(chord, key)) {
|
|
1562
1646
|
return { function: "dominant", reason: "applied" };
|
|
1563
1647
|
}
|
|
1564
|
-
if (!isMinorScale(key) && !
|
|
1648
|
+
if (!isMinorScale(key) && !_chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, key) && _chunkYDGMWH43cjs.hasMajorThird.call(void 0, chord) && (offset === 8 || offset === 10)) {
|
|
1565
1649
|
return { function: "subdominant", reason: "flatSideMajor" };
|
|
1566
1650
|
}
|
|
1567
1651
|
return { function: degreeFunction(chord, key), reason: "degree" };
|
|
@@ -1581,10 +1665,11 @@ function describeChord(fn, reason, roman, source) {
|
|
|
1581
1665
|
const head = reason === "degree" ? `${capitalize(fn)}: ${roman} takes the ${fn} function of its degree in the key` : `${capitalize(fn)}: ${roman} is ${FUNCTION_REASON_PHRASE[reason]}`;
|
|
1582
1666
|
return source === null || reason === "neapolitan" ? head : `${head}, ${BORROWED_SOURCE_PHRASE[source]}`;
|
|
1583
1667
|
}
|
|
1584
|
-
function functionAlternatives(chord,
|
|
1668
|
+
function functionAlternatives(chord, resolved, reason, accepted) {
|
|
1669
|
+
const key = resolved.scale;
|
|
1585
1670
|
const out = [];
|
|
1586
1671
|
if (reason === "degree") {
|
|
1587
|
-
if (pointsAtTonicizableDegree(chord, key) &&
|
|
1672
|
+
if (pointsAtTonicizableDegree(chord, key) && _chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, key)) {
|
|
1588
1673
|
out.push({
|
|
1589
1674
|
label: "applied dominant",
|
|
1590
1675
|
reason: "The chord is diatonic to the key, so it keeps the function of its degree rather than tonicizing another"
|
|
@@ -1599,7 +1684,7 @@ function functionAlternatives(chord, key, reason, accepted) {
|
|
|
1599
1684
|
});
|
|
1600
1685
|
}
|
|
1601
1686
|
}
|
|
1602
|
-
if (augmentedSixthKindOf(chord,
|
|
1687
|
+
if (augmentedSixthKindOf(chord, resolved) === "german") {
|
|
1603
1688
|
out.push({
|
|
1604
1689
|
label: "tritone substitute",
|
|
1605
1690
|
reason: "The German sixth sounds a dominant seventh, but the lowered submediant under it fixes the reading as an augmented sixth"
|
|
@@ -1608,18 +1693,18 @@ function functionAlternatives(chord, key, reason, accepted) {
|
|
|
1608
1693
|
return out;
|
|
1609
1694
|
}
|
|
1610
1695
|
function isDiatonic(chord, key) {
|
|
1611
|
-
return
|
|
1696
|
+
return _chunkYDGMWH43cjs.isDiatonicChord.call(void 0, _chunkYDGMWH43cjs.toChordData.call(void 0, chord), _chunkYDGMWH43cjs.toKeyScale.call(void 0, key));
|
|
1612
1697
|
}
|
|
1613
1698
|
function parallelKey(key) {
|
|
1614
|
-
return parallelScale(
|
|
1699
|
+
return parallelScale(_chunkYDGMWH43cjs.toKeyScale.call(void 0, key));
|
|
1615
1700
|
}
|
|
1616
1701
|
function analyzeChord(chord, key, opts = {}) {
|
|
1617
|
-
const asked =
|
|
1618
|
-
const data =
|
|
1619
|
-
const
|
|
1620
|
-
const source = borrowedSourceOf(data, scale);
|
|
1621
|
-
const { function: fn, reason } = functionWithReason(data,
|
|
1622
|
-
const roman = renderRoman(data,
|
|
1702
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
1703
|
+
const data = _chunkYDGMWH43cjs.toChordData.call(void 0, chord);
|
|
1704
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, key);
|
|
1705
|
+
const source = borrowedSourceOf(data, resolved.scale);
|
|
1706
|
+
const { function: fn, reason } = functionWithReason(data, resolved);
|
|
1707
|
+
const roman = renderRoman(data, resolved, asked).roman;
|
|
1623
1708
|
return {
|
|
1624
1709
|
function: fn,
|
|
1625
1710
|
borrowed: source !== null,
|
|
@@ -1627,43 +1712,41 @@ function analyzeChord(chord, key, opts = {}) {
|
|
|
1627
1712
|
roman,
|
|
1628
1713
|
rationale: describeChord(fn, reason, roman, source),
|
|
1629
1714
|
alternatives: asked.alternatives === true ? [
|
|
1630
|
-
...functionAlternatives(data,
|
|
1631
|
-
...romanAlternatives(data,
|
|
1715
|
+
...functionAlternatives(data, resolved, reason, fn),
|
|
1716
|
+
...romanAlternatives(data, resolved, asked)
|
|
1632
1717
|
] : []
|
|
1633
1718
|
};
|
|
1634
1719
|
}
|
|
1635
1720
|
function secondaryDominant(targetDegree, key) {
|
|
1636
|
-
const
|
|
1637
|
-
const
|
|
1638
|
-
|
|
1721
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, key);
|
|
1722
|
+
const scale = resolved.scale;
|
|
1723
|
+
const degreeCount = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, scale).length;
|
|
1724
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, targetDegree, "targetDegree", 1, degreeCount);
|
|
1639
1725
|
const targetRoot = degreeRootPc(targetDegree, scale);
|
|
1640
|
-
|
|
1726
|
+
const rootSpelling = _chunkS3QELJUEcjs.transposeByInterval.call(void 0, _chunkYDGMWH43cjs.keySpelling.call(void 0, targetRoot, resolved), "P5");
|
|
1727
|
+
return _chunkYDGMWH43cjs.makeSpelledChord.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, targetRoot + 7), "dom7", { rootSpelling });
|
|
1641
1728
|
}
|
|
1642
1729
|
function secondaryDominantOf(target) {
|
|
1643
|
-
const data =
|
|
1644
|
-
|
|
1645
|
-
const
|
|
1646
|
-
|
|
1647
|
-
const moved = _chunkS5BKZZGMcjs.transposeNote.call(void 0, data.rootSpelling, 7);
|
|
1648
|
-
dominant.rootSpelling = { letter: moved.letter, alter: moved.alter };
|
|
1649
|
-
}
|
|
1650
|
-
return dominant;
|
|
1730
|
+
const data = _chunkYDGMWH43cjs.toChordData.call(void 0, target);
|
|
1731
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, data.rootPc, "target chord rootPc");
|
|
1732
|
+
const rootSpelling = data.rootSpelling === void 0 ? void 0 : _chunkS3QELJUEcjs.transposeNote.call(void 0, data.rootSpelling, 7);
|
|
1733
|
+
return _chunkYDGMWH43cjs.makeSpelledChord.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, data.rootPc + 7), "dom7", { rootSpelling });
|
|
1651
1734
|
}
|
|
1652
1735
|
|
|
1653
1736
|
// src/analyze/functional/pivot.ts
|
|
1654
1737
|
var HEPTATONIC_DEGREES = 7;
|
|
1655
1738
|
function pivotChords(from, to) {
|
|
1656
|
-
return pivotsBetween(
|
|
1739
|
+
return pivotsBetween(_chunkYDGMWH43cjs.resolveKey.call(void 0, from), _chunkYDGMWH43cjs.resolveKey.call(void 0, to));
|
|
1657
1740
|
}
|
|
1658
1741
|
function pivotsBetween(from, to) {
|
|
1659
|
-
if (
|
|
1742
|
+
if (_chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, from.scale).length !== HEPTATONIC_DEGREES) {
|
|
1660
1743
|
return [];
|
|
1661
1744
|
}
|
|
1662
1745
|
const pivots = [];
|
|
1663
1746
|
const seen = /* @__PURE__ */ new Set();
|
|
1664
1747
|
for (let degree = 1; degree <= HEPTATONIC_DEGREES; degree += 1) {
|
|
1665
1748
|
const chord = stackedTriad(degree, from);
|
|
1666
|
-
if (chord === null || !
|
|
1749
|
+
if (chord === null || !_chunkYDGMWH43cjs.isDiatonicChord.call(void 0, chord, to.scale)) {
|
|
1667
1750
|
continue;
|
|
1668
1751
|
}
|
|
1669
1752
|
const identity = `${chord.rootPc}:${chord.quality}`;
|
|
@@ -1681,9 +1764,9 @@ function pivotsBetween(from, to) {
|
|
|
1681
1764
|
}
|
|
1682
1765
|
function stackedTriad(degree, key) {
|
|
1683
1766
|
try {
|
|
1684
|
-
return
|
|
1767
|
+
return _chunkYDGMWH43cjs.diatonicTriad.call(void 0, degree, key);
|
|
1685
1768
|
} catch (error) {
|
|
1686
|
-
if (error instanceof
|
|
1769
|
+
if (error instanceof _chunkS3QELJUEcjs.InvalidInputError) {
|
|
1687
1770
|
return null;
|
|
1688
1771
|
}
|
|
1689
1772
|
throw error;
|
|
@@ -1692,11 +1775,11 @@ function stackedTriad(degree, key) {
|
|
|
1692
1775
|
|
|
1693
1776
|
// src/analyze/form/internal.ts
|
|
1694
1777
|
function barSpanOf(startBeat, endBeat, meter) {
|
|
1695
|
-
const firstBar =
|
|
1696
|
-
const lastBar =
|
|
1778
|
+
const firstBar = _chunkS3QELJUEcjs.barIndexAt.call(void 0, startBeat, meter);
|
|
1779
|
+
const lastBar = _chunkS3QELJUEcjs.barIndexAt.call(void 0, endBeat, meter);
|
|
1697
1780
|
const partOf = (beat, bar) => {
|
|
1698
|
-
const barStart =
|
|
1699
|
-
const barLength =
|
|
1781
|
+
const barStart = _chunkS3QELJUEcjs.barPositionToBeat.call(void 0, { bar, beat: 0 }, meter);
|
|
1782
|
+
const barLength = _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, barStart, meter);
|
|
1700
1783
|
return barLength > 0 ? (beat - barStart) / barLength : 0;
|
|
1701
1784
|
};
|
|
1702
1785
|
return lastBar - firstBar + partOf(endBeat, lastBar) - partOf(startBeat, firstBar);
|
|
@@ -1714,35 +1797,43 @@ function firstSoundingBeat(notes, fallback = 0) {
|
|
|
1714
1797
|
}
|
|
1715
1798
|
return Number.isFinite(first) ? first : fallback;
|
|
1716
1799
|
}
|
|
1800
|
+
function resolveSpanEnd(totalBeats, startBeat, soundingEnd, name) {
|
|
1801
|
+
const given = _nullishCoalesce(totalBeats, () => ( null));
|
|
1802
|
+
if (given === null) {
|
|
1803
|
+
return Math.max(startBeat, soundingEnd);
|
|
1804
|
+
}
|
|
1805
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, given, Math.min(0, startBeat), Number.MAX_SAFE_INTEGER, name);
|
|
1806
|
+
return Math.max(startBeat, given);
|
|
1807
|
+
}
|
|
1717
1808
|
function lastBarOf(meter, spanStart, spanEnd) {
|
|
1718
|
-
const firstBar =
|
|
1719
|
-
const bar =
|
|
1720
|
-
if (bar > firstBar &&
|
|
1809
|
+
const firstBar = _chunkS3QELJUEcjs.barIndexAt.call(void 0, spanStart, meter);
|
|
1810
|
+
const bar = _chunkS3QELJUEcjs.barIndexAt.call(void 0, Math.max(spanStart, spanEnd), meter);
|
|
1811
|
+
if (bar > firstBar && _chunkS3QELJUEcjs.barPositionToBeat.call(void 0, { bar, beat: 0 }, meter) >= spanEnd - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1721
1812
|
return bar - 1;
|
|
1722
1813
|
}
|
|
1723
1814
|
return bar;
|
|
1724
1815
|
}
|
|
1725
1816
|
function sliceBars(notes, meter, spanStart, spanEnd, budget) {
|
|
1726
|
-
const firstBar =
|
|
1817
|
+
const firstBar = _chunkS3QELJUEcjs.barIndexAt.call(void 0, spanStart, meter);
|
|
1727
1818
|
const lastBar = lastBarOf(meter, spanStart, spanEnd);
|
|
1728
1819
|
const barCount = lastBar - firstBar + 1;
|
|
1729
|
-
|
|
1820
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, barCount, "form bars", budget);
|
|
1730
1821
|
const buckets = Array.from({ length: barCount }, () => []);
|
|
1731
1822
|
let memberships = 0;
|
|
1732
1823
|
for (const note of notes) {
|
|
1733
1824
|
const noteEnd = note.startBeat + note.durationBeat;
|
|
1734
|
-
const from = Math.max(firstBar,
|
|
1735
|
-
const to = Math.min(lastBar,
|
|
1825
|
+
const from = Math.max(firstBar, _chunkS3QELJUEcjs.barIndexAt.call(void 0, note.startBeat, meter));
|
|
1826
|
+
const to = Math.min(lastBar, _chunkS3QELJUEcjs.barIndexAt.call(void 0, Math.max(note.startBeat, noteEnd - _chunkS3QELJUEcjs.BEAT_EPS), meter));
|
|
1736
1827
|
memberships += Math.max(0, to - from + 1);
|
|
1737
|
-
|
|
1828
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, memberships, "form note-to-bar memberships", budget);
|
|
1738
1829
|
for (let bar = from; bar <= to; bar += 1) {
|
|
1739
1830
|
_optionalChain([buckets, 'access', _8 => _8[bar - firstBar], 'optionalAccess', _9 => _9.push, 'call', _10 => _10(note)]);
|
|
1740
1831
|
}
|
|
1741
1832
|
}
|
|
1742
1833
|
const slices = [];
|
|
1743
1834
|
for (let bar = firstBar; bar <= lastBar; bar += 1) {
|
|
1744
|
-
const startBeat =
|
|
1745
|
-
const endBeat =
|
|
1835
|
+
const startBeat = _chunkS3QELJUEcjs.barPositionToBeat.call(void 0, { bar, beat: 0 }, meter);
|
|
1836
|
+
const endBeat = _chunkS3QELJUEcjs.barPositionToBeat.call(void 0, { bar: bar + 1, beat: 0 }, meter);
|
|
1746
1837
|
const barNotes = _nullishCoalesce(buckets[bar - firstBar], () => ( []));
|
|
1747
1838
|
const { weights, totalWeight } = windowWeights(barNotes, startBeat, endBeat, meter);
|
|
1748
1839
|
slices.push({ index: bar, startBeat, endBeat, notes: barNotes, weights, totalWeight });
|
|
@@ -1760,10 +1851,10 @@ function weightSimilarity(a, b) {
|
|
|
1760
1851
|
normA += x * x;
|
|
1761
1852
|
normB += y * y;
|
|
1762
1853
|
}
|
|
1763
|
-
if (normA <=
|
|
1854
|
+
if (normA <= _chunkS3QELJUEcjs.BEAT_EPS && normB <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1764
1855
|
return 1;
|
|
1765
1856
|
}
|
|
1766
|
-
if (normA <=
|
|
1857
|
+
if (normA <= _chunkS3QELJUEcjs.BEAT_EPS || normB <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1767
1858
|
return 0;
|
|
1768
1859
|
}
|
|
1769
1860
|
return clamp01(dot / Math.sqrt(normA * normB));
|
|
@@ -1790,13 +1881,23 @@ function combineEvidence(strengths) {
|
|
|
1790
1881
|
// src/analyze/grid.ts
|
|
1791
1882
|
function gridOriginOf(firstOnset, slotBeats) {
|
|
1792
1883
|
const startBeat = firstOnset < 0 && firstOnset > -HUMANIZE_ADJACENCY ? 0 : firstOnset;
|
|
1793
|
-
return { origin: Math.floor(startBeat / slotBeats +
|
|
1884
|
+
return { origin: Math.floor(startBeat / slotBeats + _chunkS3QELJUEcjs.BEAT_EPS) * slotBeats, startBeat };
|
|
1794
1885
|
}
|
|
1795
1886
|
function gridForNotes(notes, slotBeats) {
|
|
1796
1887
|
return gridOriginOf(firstSoundingBeat(notes), slotBeats);
|
|
1797
1888
|
}
|
|
1889
|
+
function latestSoundingEnd(notes, fallback = 0) {
|
|
1890
|
+
if (notes.length === 0) {
|
|
1891
|
+
return fallback;
|
|
1892
|
+
}
|
|
1893
|
+
let end = Number.NEGATIVE_INFINITY;
|
|
1894
|
+
for (const note of notes) {
|
|
1895
|
+
end = Math.max(end, note.startBeat + note.durationBeat);
|
|
1896
|
+
}
|
|
1897
|
+
return end;
|
|
1898
|
+
}
|
|
1798
1899
|
function barGridStart(firstOnset, meter) {
|
|
1799
|
-
return gridOriginOf(firstOnset,
|
|
1900
|
+
return gridOriginOf(firstOnset, _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, firstOnset, meter)).startBeat;
|
|
1800
1901
|
}
|
|
1801
1902
|
|
|
1802
1903
|
// src/analyze/keys/index.ts
|
|
@@ -1816,13 +1917,13 @@ var FIFTHS_DISTANCE_COST = 0.18;
|
|
|
1816
1917
|
var KEY_CANDIDATES = (() => {
|
|
1817
1918
|
const candidates = [];
|
|
1818
1919
|
for (let rootPc = 0; rootPc < 12; rootPc += 1) {
|
|
1819
|
-
candidates.push({ key:
|
|
1820
|
-
candidates.push({ key:
|
|
1920
|
+
candidates.push({ key: _chunkYDGMWH43cjs.majorKey.call(void 0, rootPc), rootPc, minor: false });
|
|
1921
|
+
candidates.push({ key: _chunkYDGMWH43cjs.minorKey.call(void 0, rootPc), rootPc, minor: true });
|
|
1821
1922
|
}
|
|
1822
1923
|
return candidates;
|
|
1823
1924
|
})();
|
|
1824
1925
|
function fifthsOf(rootPc, minor) {
|
|
1825
|
-
const majorRoot =
|
|
1926
|
+
const majorRoot = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, minor ? rootPc + 3 : rootPc);
|
|
1826
1927
|
const raw = majorRoot * 7 % 12;
|
|
1827
1928
|
return raw > 6 ? raw - 12 : raw;
|
|
1828
1929
|
}
|
|
@@ -1840,9 +1941,9 @@ function chooseKeys(slots, changeCost, meter, budget) {
|
|
|
1840
1941
|
if (slots.length === 0) {
|
|
1841
1942
|
return [];
|
|
1842
1943
|
}
|
|
1843
|
-
const back =
|
|
1844
|
-
let costs =
|
|
1845
|
-
let spare =
|
|
1944
|
+
const back = _chunkS3QELJUEcjs.allocateChoiceTable.call(void 0, slots.length, count, "key search choices", budget);
|
|
1945
|
+
let costs = _chunkS3QELJUEcjs.allocateCandidateTable.call(void 0, 1, count, "key search costs", budget);
|
|
1946
|
+
let spare = _chunkS3QELJUEcjs.allocateCandidateTable.call(void 0, 1, count, "key search costs", budget);
|
|
1846
1947
|
const opening = _nullishCoalesce(_optionalChain([slots, 'access', _11 => _11[0], 'optionalAccess', _12 => _12.scores]), () => ( []));
|
|
1847
1948
|
for (let c = 0; c < count; c += 1) {
|
|
1848
1949
|
costs[c] = -(_nullishCoalesce(opening[c], () => ( 0)));
|
|
@@ -1851,7 +1952,7 @@ function chooseKeys(slots, changeCost, meter, budget) {
|
|
|
1851
1952
|
const slot = slots[i];
|
|
1852
1953
|
const previous = costs;
|
|
1853
1954
|
const next = spare;
|
|
1854
|
-
const accent =
|
|
1955
|
+
const accent = _chunkS3QELJUEcjs.metricWeight.call(void 0, _nullishCoalesce(_optionalChain([slot, 'optionalAccess', _13 => _13.startBeat]), () => ( 0)), meter);
|
|
1855
1956
|
const metricFactor = 1 - STRONG_BEAT_DISCOUNT * accent / MAX_METRIC_WEIGHT;
|
|
1856
1957
|
const rowBase = i * count;
|
|
1857
1958
|
for (let to = 0; to < count; to += 1) {
|
|
@@ -1921,7 +2022,7 @@ function enforceMinimumRegion(slots, path, minBeats, budget) {
|
|
|
1921
2022
|
return chosen;
|
|
1922
2023
|
}
|
|
1923
2024
|
const candidates = KEY_CANDIDATES.length;
|
|
1924
|
-
const totals =
|
|
2025
|
+
const totals = _chunkS3QELJUEcjs.allocateCandidateTable.call(void 0, slots.length, candidates, "key region scores", budget);
|
|
1925
2026
|
for (let i = 0; i < slots.length; i += 1) {
|
|
1926
2027
|
const scores = _nullishCoalesce(_optionalChain([slots, 'access', _18 => _18[i], 'optionalAccess', _19 => _19.scores]), () => ( []));
|
|
1927
2028
|
const base = i * candidates;
|
|
@@ -1952,13 +2053,13 @@ function enforceMinimumRegion(slots, path, minBeats, budget) {
|
|
|
1952
2053
|
return chosen;
|
|
1953
2054
|
}
|
|
1954
2055
|
const length = region.endBeat - region.startBeat;
|
|
1955
|
-
if (region.merged || length >= minBeats -
|
|
2056
|
+
if (region.merged || length >= minBeats - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1956
2057
|
continue;
|
|
1957
2058
|
}
|
|
1958
2059
|
const previous = region.previous;
|
|
1959
2060
|
const next = region.next;
|
|
1960
|
-
const before = previous !== void 0 && Math.abs(previous.endBeat - region.startBeat) <
|
|
1961
|
-
const after = next !== void 0 && Math.abs(next.startBeat - region.endBeat) <
|
|
2061
|
+
const before = previous !== void 0 && Math.abs(previous.endBeat - region.startBeat) < _chunkS3QELJUEcjs.BEAT_EPS ? previous : void 0;
|
|
2062
|
+
const after = next !== void 0 && Math.abs(next.startBeat - region.endBeat) < _chunkS3QELJUEcjs.BEAT_EPS ? next : void 0;
|
|
1962
2063
|
if (before === void 0 && after === void 0) {
|
|
1963
2064
|
continue;
|
|
1964
2065
|
}
|
|
@@ -2068,7 +2169,7 @@ function withRelations(regions) {
|
|
|
2068
2169
|
if (previous === void 0 || current === void 0) {
|
|
2069
2170
|
continue;
|
|
2070
2171
|
}
|
|
2071
|
-
const relation =
|
|
2172
|
+
const relation = _chunkYDGMWH43cjs.keyRelationBetween.call(void 0, previous.key, current.key);
|
|
2072
2173
|
if (relation !== null && relation !== "same") {
|
|
2073
2174
|
current.modulation = relation;
|
|
2074
2175
|
}
|
|
@@ -2076,22 +2177,26 @@ function withRelations(regions) {
|
|
|
2076
2177
|
return regions;
|
|
2077
2178
|
}
|
|
2078
2179
|
function keyTimelineFromNotes(notes, opts = {}) {
|
|
2079
|
-
const meters =
|
|
2080
|
-
const bar =
|
|
2180
|
+
const meters = _chunkS3QELJUEcjs.resolveMeters.call(void 0, opts, "key timeline meters");
|
|
2181
|
+
const bar = _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, 0, meters);
|
|
2081
2182
|
const expectedKeyBeats = _nullishCoalesce(opts.expectedKeyBeats, () => ( bar * 4));
|
|
2082
|
-
|
|
2183
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, expectedKeyBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "expectedKeyBeats");
|
|
2083
2184
|
const minKeyBeats = _nullishCoalesce(opts.minKeyBeats, () => ( bar));
|
|
2084
|
-
|
|
2185
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, minKeyBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "minKeyBeats");
|
|
2085
2186
|
const budget = opts.budget;
|
|
2086
|
-
|
|
2187
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, notes, "key timeline notes", { allowNonPositiveDuration: true, budget });
|
|
2087
2188
|
const sounding = notes.filter((note) => note.durationBeat > 0);
|
|
2088
|
-
const
|
|
2089
|
-
|
|
2090
|
-
|
|
2189
|
+
const totalBeats = _nullishCoalesce(opts.totalBeats, () => ( latestSoundingEnd(sounding)));
|
|
2190
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0,
|
|
2191
|
+
totalBeats,
|
|
2192
|
+
Math.min(0, firstSoundingBeat(sounding)),
|
|
2193
|
+
Number.MAX_SAFE_INTEGER,
|
|
2194
|
+
"key timeline totalBeats"
|
|
2195
|
+
);
|
|
2091
2196
|
const slotBeats = Math.min(minKeyBeats, expectedKeyBeats);
|
|
2092
2197
|
const { origin, startBeat: musicStart } = gridForNotes(sounding, slotBeats);
|
|
2093
|
-
const slotCount = Math.max(0, Math.ceil((totalBeats - origin) / slotBeats -
|
|
2094
|
-
|
|
2198
|
+
const slotCount = Math.max(0, Math.ceil((totalBeats - origin) / slotBeats - _chunkS3QELJUEcjs.BEAT_EPS));
|
|
2199
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, slotCount * KEY_CANDIDATES.length, "key timeline slots", budget);
|
|
2095
2200
|
if (slotCount === 0 || sounding.length === 0) {
|
|
2096
2201
|
return [];
|
|
2097
2202
|
}
|
|
@@ -2129,7 +2234,7 @@ function keyTimelineFromNotes(notes, opts = {}) {
|
|
|
2129
2234
|
(candidate) => profileScore(weights, candidate.minor ? profile.minor : profile.major, candidate.rootPc) * totalWeight
|
|
2130
2235
|
);
|
|
2131
2236
|
slots.push({ startBeat, endBeat, scores, weight: totalWeight });
|
|
2132
|
-
if (totalWeight >
|
|
2237
|
+
if (totalWeight > _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2133
2238
|
weightSum += totalWeight;
|
|
2134
2239
|
soundingSlots += 1;
|
|
2135
2240
|
}
|
|
@@ -2143,14 +2248,14 @@ function keyTimelineFromNotes(notes, opts = {}) {
|
|
|
2143
2248
|
const grouped = regionsFromPath(slots, path);
|
|
2144
2249
|
const head = grouped[0];
|
|
2145
2250
|
const next = grouped[1];
|
|
2146
|
-
if (head !== void 0 && next !== void 0 && head.endBeat - Math.max(head.startBeat, musicStart) < slotBeats -
|
|
2251
|
+
if (head !== void 0 && next !== void 0 && head.endBeat - Math.max(head.startBeat, musicStart) < slotBeats - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2147
2252
|
next.startBeat = head.startBeat;
|
|
2148
2253
|
next.from = head.from;
|
|
2149
2254
|
grouped.shift();
|
|
2150
2255
|
}
|
|
2151
2256
|
const regions = grouped.map((region) => {
|
|
2152
2257
|
const candidate = KEY_CANDIDATES[region.candidate];
|
|
2153
|
-
const key =
|
|
2258
|
+
const key = _chunkYDGMWH43cjs.resolveKey.call(void 0, _nullishCoalesce(_optionalChain([candidate, 'optionalAccess', _24 => _24.key]), () => ( _chunkYDGMWH43cjs.majorKey.call(void 0, 0))));
|
|
2154
2259
|
const startBeat = Math.max(region.startBeat, musicStart);
|
|
2155
2260
|
const weights = new Array(PITCH_CLASSES).fill(0);
|
|
2156
2261
|
for (let i = region.from; i < region.toExclusive; i += 1) {
|
|
@@ -2170,7 +2275,7 @@ function keyTimelineFromNotes(notes, opts = {}) {
|
|
|
2170
2275
|
return {
|
|
2171
2276
|
startBeat,
|
|
2172
2277
|
endBeat: region.endBeat,
|
|
2173
|
-
key:
|
|
2278
|
+
key: _chunkYDGMWH43cjs.resolveKey.call(void 0, key),
|
|
2174
2279
|
confidence: Math.max(0, correlation)
|
|
2175
2280
|
};
|
|
2176
2281
|
});
|
|
@@ -2182,20 +2287,20 @@ var TONIC_CREDIT = 0.4;
|
|
|
2182
2287
|
var CADENCE_CREDIT = 0.6;
|
|
2183
2288
|
var CHORD_MODULATION_COST = 0.6;
|
|
2184
2289
|
function chordFitsKey(chord, candidate) {
|
|
2185
|
-
const tones =
|
|
2290
|
+
const tones = _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord);
|
|
2186
2291
|
if (tones.length === 0) {
|
|
2187
2292
|
return 0;
|
|
2188
2293
|
}
|
|
2189
2294
|
let inKey = 0;
|
|
2190
2295
|
for (const pc of tones) {
|
|
2191
|
-
if (
|
|
2296
|
+
if (_chunkYDGMWH43cjs.isScaleTone.call(void 0, pc, candidate.key)) {
|
|
2192
2297
|
inKey += 1;
|
|
2193
2298
|
}
|
|
2194
2299
|
}
|
|
2195
2300
|
let score = CHORD_TONE_CREDIT * ((inKey - (tones.length - inKey)) / tones.length);
|
|
2196
|
-
const rootDegree =
|
|
2301
|
+
const rootDegree = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc - candidate.rootPc);
|
|
2197
2302
|
if (rootDegree === 7) {
|
|
2198
|
-
if (
|
|
2303
|
+
if (_chunkYDGMWH43cjs.soundsDominantSeventh.call(void 0, chord)) {
|
|
2199
2304
|
score += DOMINANT_CREDIT;
|
|
2200
2305
|
} else if (chord.quality === "maj") {
|
|
2201
2306
|
score += DOMINANT_CREDIT * 0.5;
|
|
@@ -2207,25 +2312,26 @@ function chordFitsKey(chord, candidate) {
|
|
|
2207
2312
|
return score;
|
|
2208
2313
|
}
|
|
2209
2314
|
function detectModulations(chords, opts = {}) {
|
|
2210
|
-
|
|
2315
|
+
_chunkS3QELJUEcjs.assertArray.call(void 0, chords, "modulation chord segments");
|
|
2211
2316
|
chords.forEach((segment, index) => {
|
|
2212
|
-
|
|
2317
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, segment, `modulation chord segments[${index}]`);
|
|
2213
2318
|
});
|
|
2214
|
-
const meters =
|
|
2215
|
-
const bar =
|
|
2319
|
+
const meters = _chunkS3QELJUEcjs.resolveMeters.call(void 0, opts, "modulation meters");
|
|
2320
|
+
const bar = _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, 0, meters);
|
|
2216
2321
|
const expectedKeyBeats = _nullishCoalesce(opts.expectedKeyBeats, () => ( bar * 4));
|
|
2217
|
-
|
|
2322
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, expectedKeyBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "expectedKeyBeats");
|
|
2218
2323
|
const minKeyBeats = _nullishCoalesce(opts.minKeyBeats, () => ( bar));
|
|
2219
|
-
|
|
2220
|
-
|
|
2324
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, minKeyBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "minKeyBeats");
|
|
2325
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0,
|
|
2221
2326
|
chords.length * KEY_CANDIDATES.length,
|
|
2222
2327
|
"modulation chord segments",
|
|
2223
2328
|
opts.budget
|
|
2224
2329
|
);
|
|
2225
2330
|
const sorted = [...chords].filter((segment) => segment.endBeat > segment.startBeat).sort((a, b) => a.startBeat - b.startBeat);
|
|
2226
|
-
const lastChordEnd = sorted.reduce((end, segment) => Math.max(end, segment.endBeat),
|
|
2331
|
+
const lastChordEnd = sorted.length === 0 ? 0 : sorted.reduce((end, segment) => Math.max(end, segment.endBeat), Number.NEGATIVE_INFINITY);
|
|
2227
2332
|
const totalBeats = _nullishCoalesce(opts.totalBeats, () => ( lastChordEnd));
|
|
2228
|
-
|
|
2333
|
+
const lowest = totalBeats < 0 ? Math.min(0, _nullishCoalesce(_optionalChain([sorted, 'access', _27 => _27[0], 'optionalAccess', _28 => _28.startBeat]), () => ( 0))) : 0;
|
|
2334
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, totalBeats, lowest, Number.MAX_SAFE_INTEGER, "modulation totalBeats");
|
|
2229
2335
|
const ordered = sorted.map((segment) => ({ ...segment, endBeat: Math.min(segment.endBeat, totalBeats) })).filter((segment) => segment.endBeat > segment.startBeat);
|
|
2230
2336
|
if (ordered.length === 0) {
|
|
2231
2337
|
return [];
|
|
@@ -2242,20 +2348,20 @@ function detectModulations(chords, opts = {}) {
|
|
|
2242
2348
|
};
|
|
2243
2349
|
});
|
|
2244
2350
|
for (let i = 1; i < slots.length; i += 1) {
|
|
2245
|
-
const arriving = _optionalChain([ordered, 'access',
|
|
2246
|
-
const approaching = _optionalChain([ordered, 'access',
|
|
2351
|
+
const arriving = _optionalChain([ordered, 'access', _29 => _29[i], 'optionalAccess', _30 => _30.chord]);
|
|
2352
|
+
const approaching = _optionalChain([ordered, 'access', _31 => _31[i - 1], 'optionalAccess', _32 => _32.chord]);
|
|
2247
2353
|
const slot = slots[i];
|
|
2248
2354
|
if (arriving === void 0 || approaching === void 0 || slot === void 0) {
|
|
2249
2355
|
continue;
|
|
2250
2356
|
}
|
|
2251
|
-
const isDominantMotion =
|
|
2357
|
+
const isDominantMotion = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, approaching.rootPc - arriving.rootPc) === 7 && _chunkYDGMWH43cjs.soundsDominantSeventh.call(void 0, approaching);
|
|
2252
2358
|
if (!isDominantMotion) {
|
|
2253
2359
|
continue;
|
|
2254
2360
|
}
|
|
2255
2361
|
const length = slot.endBeat - slot.startBeat;
|
|
2256
2362
|
for (let c = 0; c < KEY_CANDIDATES.length; c += 1) {
|
|
2257
2363
|
const candidate = KEY_CANDIDATES[c];
|
|
2258
|
-
if (candidate !== void 0 &&
|
|
2364
|
+
if (candidate !== void 0 && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, arriving.rootPc - candidate.rootPc) === 0) {
|
|
2259
2365
|
slot.scores[c] = (_nullishCoalesce(slot.scores[c], () => ( 0))) + CADENCE_CREDIT * length;
|
|
2260
2366
|
}
|
|
2261
2367
|
}
|
|
@@ -2269,7 +2375,7 @@ function detectModulations(chords, opts = {}) {
|
|
|
2269
2375
|
const profile = resolveKeyProfile(opts.profile);
|
|
2270
2376
|
const regions = grouped.map((region) => {
|
|
2271
2377
|
const candidate = KEY_CANDIDATES[region.candidate];
|
|
2272
|
-
const key =
|
|
2378
|
+
const key = _chunkYDGMWH43cjs.resolveKey.call(void 0, _nullishCoalesce(_optionalChain([candidate, 'optionalAccess', _33 => _33.key]), () => ( _chunkYDGMWH43cjs.majorKey.call(void 0, 0))));
|
|
2273
2379
|
const weights = new Array(PITCH_CLASSES).fill(0);
|
|
2274
2380
|
for (let i = region.from; i < region.toExclusive; i += 1) {
|
|
2275
2381
|
const segment = ordered[i];
|
|
@@ -2277,17 +2383,17 @@ function detectModulations(chords, opts = {}) {
|
|
|
2277
2383
|
continue;
|
|
2278
2384
|
}
|
|
2279
2385
|
const overlap = segment.endBeat - segment.startBeat;
|
|
2280
|
-
if (overlap <=
|
|
2386
|
+
if (overlap <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2281
2387
|
continue;
|
|
2282
2388
|
}
|
|
2283
|
-
for (const pc of
|
|
2389
|
+
for (const pc of _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, segment.chord)) {
|
|
2284
2390
|
weights[pc] = (_nullishCoalesce(weights[pc], () => ( 0))) + overlap;
|
|
2285
2391
|
}
|
|
2286
2392
|
}
|
|
2287
2393
|
const correlation = profileScore(
|
|
2288
2394
|
weights,
|
|
2289
|
-
_optionalChain([candidate, 'optionalAccess',
|
|
2290
|
-
_nullishCoalesce(_optionalChain([candidate, 'optionalAccess',
|
|
2395
|
+
_optionalChain([candidate, 'optionalAccess', _34 => _34.minor]) ? profile.minor : profile.major,
|
|
2396
|
+
_nullishCoalesce(_optionalChain([candidate, 'optionalAccess', _35 => _35.rootPc]), () => ( 0))
|
|
2291
2397
|
);
|
|
2292
2398
|
return {
|
|
2293
2399
|
startBeat: region.startBeat,
|
|
@@ -2305,7 +2411,7 @@ function detectModulations(chords, opts = {}) {
|
|
|
2305
2411
|
var THIRD_SEMITONES = [3, 4];
|
|
2306
2412
|
var FIFTH_SEMITONES = [6, 7, 8];
|
|
2307
2413
|
function triadCore(chord) {
|
|
2308
|
-
const root =
|
|
2414
|
+
const root = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc);
|
|
2309
2415
|
let third;
|
|
2310
2416
|
let fifth;
|
|
2311
2417
|
for (const interval of chord.intervals) {
|
|
@@ -2321,10 +2427,10 @@ function triadCore(chord) {
|
|
|
2321
2427
|
if (third === void 0 || fifth === void 0) {
|
|
2322
2428
|
return null;
|
|
2323
2429
|
}
|
|
2324
|
-
return [root,
|
|
2430
|
+
return [root, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, root + third), _chunkS3QELJUEcjs.pitchClassOf.call(void 0, root + fifth)].sort((a, b) => a - b);
|
|
2325
2431
|
}
|
|
2326
2432
|
function lastChordFinishedBy(chords) {
|
|
2327
|
-
const byEnd = chords.map((_, index) => index).sort((a, b) => (_nullishCoalesce(_optionalChain([chords, 'access',
|
|
2433
|
+
const byEnd = chords.map((_, index) => index).sort((a, b) => (_nullishCoalesce(_optionalChain([chords, 'access', _36 => _36[a], 'optionalAccess', _37 => _37.endBeat]), () => ( 0))) - (_nullishCoalesce(_optionalChain([chords, 'access', _38 => _38[b], 'optionalAccess', _39 => _39.endBeat]), () => ( 0))));
|
|
2328
2434
|
const latest = new Int32Array(byEnd.length);
|
|
2329
2435
|
let running = 0;
|
|
2330
2436
|
for (let i = 0; i < byEnd.length; i += 1) {
|
|
@@ -2336,7 +2442,7 @@ function lastChordFinishedBy(chords) {
|
|
|
2336
2442
|
let high = byEnd.length;
|
|
2337
2443
|
while (low < high) {
|
|
2338
2444
|
const mid = low + high >> 1;
|
|
2339
|
-
if ((_nullishCoalesce(_optionalChain([chords, 'access',
|
|
2445
|
+
if ((_nullishCoalesce(_optionalChain([chords, 'access', _40 => _40[_nullishCoalesce(byEnd[mid], () => ( 0))], 'optionalAccess', _41 => _41.endBeat]), () => ( 0))) <= beat) {
|
|
2340
2446
|
low = mid + 1;
|
|
2341
2447
|
} else {
|
|
2342
2448
|
high = mid;
|
|
@@ -2359,7 +2465,7 @@ function attachPivots(regions, chords) {
|
|
|
2359
2465
|
if (previous === void 0 || current === void 0) {
|
|
2360
2466
|
continue;
|
|
2361
2467
|
}
|
|
2362
|
-
const last = finished(current.startBeat +
|
|
2468
|
+
const last = finished(current.startBeat + _chunkS3QELJUEcjs.BEAT_EPS);
|
|
2363
2469
|
if (last === void 0) {
|
|
2364
2470
|
continue;
|
|
2365
2471
|
}
|
|
@@ -2367,9 +2473,9 @@ function attachPivots(regions, chords) {
|
|
|
2367
2473
|
if (core === null) {
|
|
2368
2474
|
continue;
|
|
2369
2475
|
}
|
|
2370
|
-
const root =
|
|
2476
|
+
const root = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, last.chord.rootPc);
|
|
2371
2477
|
const pivot = pivotChords(previous.key, current.key).find(
|
|
2372
|
-
(entry) => entry.chord.rootPc === root && sameTones(
|
|
2478
|
+
(entry) => entry.chord.rootPc === root && sameTones(_chunkYDGMWH43cjs.chordPitchClasses.call(void 0, entry.chord), core)
|
|
2373
2479
|
);
|
|
2374
2480
|
if (pivot !== void 0) {
|
|
2375
2481
|
current.pivot = pivot;
|
|
@@ -2383,7 +2489,7 @@ function keyLookup(regions, fallback) {
|
|
|
2383
2489
|
let high = regions.length;
|
|
2384
2490
|
while (low < high) {
|
|
2385
2491
|
const middle = Math.floor((low + high) / 2);
|
|
2386
|
-
if ((_nullishCoalesce(_optionalChain([regions, 'access',
|
|
2492
|
+
if ((_nullishCoalesce(_optionalChain([regions, 'access', _42 => _42[middle], 'optionalAccess', _43 => _43.startBeat]), () => ( Number.POSITIVE_INFINITY))) <= beat) {
|
|
2387
2493
|
low = middle + 1;
|
|
2388
2494
|
} else {
|
|
2389
2495
|
high = middle;
|
|
@@ -2394,12 +2500,12 @@ function keyLookup(regions, fallback) {
|
|
|
2394
2500
|
};
|
|
2395
2501
|
}
|
|
2396
2502
|
function prevailingKeyOf(regions) {
|
|
2397
|
-
|
|
2503
|
+
_chunkS3QELJUEcjs.assertArray.call(void 0, regions, "key regions");
|
|
2398
2504
|
const totals = /* @__PURE__ */ new Map();
|
|
2399
2505
|
for (const [index, given] of regions.entries()) {
|
|
2400
|
-
const region =
|
|
2401
|
-
|
|
2402
|
-
const id = `${
|
|
2506
|
+
const region = _chunkS3QELJUEcjs.assertRecord.call(void 0, given, `key regions[${index}]`);
|
|
2507
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, region.key, `key regions[${index}].key`);
|
|
2508
|
+
const id = `${_chunkS3QELJUEcjs.pitchClassOf.call(void 0, region.key.scale.rootPc)}:${region.key.scale.modeMask12}`;
|
|
2403
2509
|
const entry = totals.get(id);
|
|
2404
2510
|
const length = Math.max(0, region.endBeat - region.startBeat);
|
|
2405
2511
|
if (entry === void 0) {
|
|
@@ -2422,13 +2528,13 @@ function prevailingKeyOf(regions) {
|
|
|
2422
2528
|
// src/analyze/voice/index.ts
|
|
2423
2529
|
function keyScaleAt(key) {
|
|
2424
2530
|
if (typeof key === "function") {
|
|
2425
|
-
return key;
|
|
2531
|
+
return (beat) => _chunkYDGMWH43cjs.toKeyScale.call(void 0, key(beat));
|
|
2426
2532
|
}
|
|
2427
|
-
const scale =
|
|
2533
|
+
const scale = _chunkYDGMWH43cjs.toKeyScale.call(void 0, key);
|
|
2428
2534
|
return () => scale;
|
|
2429
2535
|
}
|
|
2430
2536
|
function toVoiceNotes(events) {
|
|
2431
|
-
|
|
2537
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, events, "voice notes", { allowNonPositiveDuration: true });
|
|
2432
2538
|
return events.map((event, index) => ({ ...event, id: index, originalIndex: index }));
|
|
2433
2539
|
}
|
|
2434
2540
|
function intervalAboveBass(pitch, others, chord) {
|
|
@@ -2440,7 +2546,7 @@ function intervalAboveBass(pitch, others, chord) {
|
|
|
2440
2546
|
return ((pitch - bass) % 12 + 12) % 12;
|
|
2441
2547
|
}
|
|
2442
2548
|
const ref = _nullishCoalesce(chord.bassPc, () => ( chord.rootPc));
|
|
2443
|
-
return ((
|
|
2549
|
+
return ((_chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch) - _chunkS3QELJUEcjs.pitchClassOf.call(void 0, ref)) % 12 + 12) % 12;
|
|
2444
2550
|
}
|
|
2445
2551
|
var TENSION_DEGREE_BY_INTERVAL = {
|
|
2446
2552
|
1: 9,
|
|
@@ -2451,7 +2557,8 @@ var TENSION_DEGREE_BY_INTERVAL = {
|
|
|
2451
2557
|
8: 13,
|
|
2452
2558
|
9: 13
|
|
2453
2559
|
};
|
|
2454
|
-
var
|
|
2560
|
+
var NATURAL_TENSION_INTERVAL_LIST = [2, 5, 9];
|
|
2561
|
+
var NATURAL_TENSION_INTERVALS = new Set(NATURAL_TENSION_INTERVAL_LIST);
|
|
2455
2562
|
function tensionDegree(ic) {
|
|
2456
2563
|
return TENSION_DEGREE_BY_INTERVAL[ic];
|
|
2457
2564
|
}
|
|
@@ -2459,18 +2566,29 @@ function asSounded(chord) {
|
|
|
2459
2566
|
if (chord.bassPc === void 0) {
|
|
2460
2567
|
return chord;
|
|
2461
2568
|
}
|
|
2462
|
-
return { ...chord, intervals: [...chord.intervals,
|
|
2569
|
+
return { ...chord, intervals: [...chord.intervals, _chunkYDGMWH43cjs.intervalAboveRoot.call(void 0, chord.bassPc, chord)] };
|
|
2463
2570
|
}
|
|
2464
2571
|
function isStep(a, b) {
|
|
2465
2572
|
const d = Math.abs(a - b);
|
|
2466
2573
|
return d === 1 || d === 2;
|
|
2467
2574
|
}
|
|
2468
2575
|
var LEAP_SEMITONES = 3;
|
|
2469
|
-
function suspensionType(ic, delta) {
|
|
2576
|
+
function suspensionType(ic, delta, resolvedIc) {
|
|
2577
|
+
const figure = suspendedFigure(ic, delta);
|
|
2578
|
+
return figure !== null && SUSPENSION_RESOLUTIONS[figure].includes(resolvedIc) ? figure : null;
|
|
2579
|
+
}
|
|
2580
|
+
var SUSPENSION_RESOLUTIONS = {
|
|
2581
|
+
"sus4-3": [3, 4],
|
|
2582
|
+
"sus6-5": [7],
|
|
2583
|
+
"sus7-6": [8, 9],
|
|
2584
|
+
"sus9-8": [0],
|
|
2585
|
+
"sus2-3": [3, 4]
|
|
2586
|
+
};
|
|
2587
|
+
function suspendedFigure(ic, delta) {
|
|
2470
2588
|
if (delta > 0) {
|
|
2471
2589
|
return ic === 1 || ic === 2 ? "sus2-3" : null;
|
|
2472
2590
|
}
|
|
2473
|
-
if (ic === 2) {
|
|
2591
|
+
if (ic === 1 || ic === 2) {
|
|
2474
2592
|
return "sus9-8";
|
|
2475
2593
|
}
|
|
2476
2594
|
if (ic === 10 || ic === 11) {
|
|
@@ -2484,43 +2602,58 @@ function suspensionType(ic, delta) {
|
|
|
2484
2602
|
}
|
|
2485
2603
|
return null;
|
|
2486
2604
|
}
|
|
2605
|
+
function clashesWithChord(pitch, chord) {
|
|
2606
|
+
if (!_chunkS3QELJUEcjs.isConsonantInterval.call(void 0, intervalAboveBass(pitch, [], chord), true)) {
|
|
2607
|
+
return true;
|
|
2608
|
+
}
|
|
2609
|
+
const tones = chord.intervals.map((interval) => chord.rootPc + interval);
|
|
2610
|
+
if (chord.bassPc !== void 0) {
|
|
2611
|
+
tones.push(chord.bassPc);
|
|
2612
|
+
}
|
|
2613
|
+
return tones.some(
|
|
2614
|
+
(tone) => !_chunkS3QELJUEcjs.isConsonantInterval.call(void 0, ((_chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch) - tone) % 12 + 12) % 12, false)
|
|
2615
|
+
);
|
|
2616
|
+
}
|
|
2487
2617
|
var STEP_RESOLUTION = 2;
|
|
2488
2618
|
var NEAREST_CHORD_TONE_REACH = 12;
|
|
2489
2619
|
function nearestChordTone(pitch, chord, maxDistance) {
|
|
2490
2620
|
for (let delta = 1; delta <= maxDistance; delta += 1) {
|
|
2491
|
-
if (
|
|
2621
|
+
if (_chunkYDGMWH43cjs.isChordMember.call(void 0, pitch - delta, chord)) {
|
|
2492
2622
|
return pitch - delta;
|
|
2493
2623
|
}
|
|
2494
|
-
if (
|
|
2624
|
+
if (_chunkYDGMWH43cjs.isChordMember.call(void 0, pitch + delta, chord)) {
|
|
2495
2625
|
return pitch + delta;
|
|
2496
2626
|
}
|
|
2497
2627
|
}
|
|
2498
2628
|
return void 0;
|
|
2499
2629
|
}
|
|
2500
2630
|
function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2631
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, voice, "voice notes", { allowNonPositiveDuration: true });
|
|
2632
|
+
_chunkS3QELJUEcjs.assertFunction.call(void 0, chordAtBeat2, "chordAtBeat");
|
|
2633
|
+
_chunkS3QELJUEcjs.assertFunction.call(void 0, otherVoicesAtBeat, "otherVoicesAtBeat");
|
|
2504
2634
|
const keyAt = keyScaleAt(key);
|
|
2505
2635
|
const result = [];
|
|
2636
|
+
const sounding = _chunkKMYGRFZ6cjs.soundingIndices.call(void 0, voice);
|
|
2637
|
+
const line = new Map(sounding.map((index, position) => [index, position]));
|
|
2506
2638
|
for (let i = 0; i < voice.length; i += 1) {
|
|
2507
2639
|
const note = voice[i];
|
|
2508
2640
|
if (!note) {
|
|
2509
2641
|
continue;
|
|
2510
2642
|
}
|
|
2511
|
-
const
|
|
2512
|
-
const
|
|
2513
|
-
const
|
|
2514
|
-
const
|
|
2515
|
-
const
|
|
2516
|
-
const
|
|
2643
|
+
const position = line.get(i);
|
|
2644
|
+
const prevIndex = position === void 0 ? void 0 : sounding[position - 1];
|
|
2645
|
+
const nextIndex = position === void 0 ? void 0 : sounding[position + 1];
|
|
2646
|
+
const prevNote = prevIndex === void 0 ? void 0 : voice[prevIndex];
|
|
2647
|
+
const nextNote = nextIndex === void 0 ? void 0 : voice[nextIndex];
|
|
2648
|
+
const prev = prevNote !== void 0 && !sameInstant(prevNote.startBeat, note.startBeat) && adjacent(prevNote.startBeat + prevNote.durationBeat, note.startBeat) ? prevNote : void 0;
|
|
2649
|
+
const next = nextNote !== void 0 && !sameInstant(nextNote.startBeat, note.startBeat) && adjacent(note.startBeat + note.durationBeat, nextNote.startBeat) ? nextNote : void 0;
|
|
2517
2650
|
const chord = chordAtBeat2(note.startBeat);
|
|
2518
2651
|
const labels = [];
|
|
2519
|
-
const member =
|
|
2652
|
+
const member = _chunkYDGMWH43cjs.isChordMember.call(void 0, note.pitch, chord);
|
|
2520
2653
|
let handled = false;
|
|
2521
2654
|
if (chord && member) {
|
|
2522
|
-
const role =
|
|
2523
|
-
const degree = role === null ? tensionDegree(
|
|
2655
|
+
const role = _chunkYDGMWH43cjs.chordToneRole.call(void 0, note.pitch, chord);
|
|
2656
|
+
const degree = role === null ? tensionDegree(_chunkYDGMWH43cjs.intervalAboveRoot.call(void 0, note.pitch, chord)) : void 0;
|
|
2524
2657
|
if (role) {
|
|
2525
2658
|
labels.push({ kind: "chordTone", role });
|
|
2526
2659
|
handled = true;
|
|
@@ -2528,7 +2661,7 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2528
2661
|
labels.push({ kind: "tension", degree });
|
|
2529
2662
|
handled = true;
|
|
2530
2663
|
} else {
|
|
2531
|
-
const bassRole =
|
|
2664
|
+
const bassRole = _chunkYDGMWH43cjs.chordToneRole.call(void 0, note.pitch, asSounded(chord));
|
|
2532
2665
|
if (bassRole !== null) {
|
|
2533
2666
|
labels.push({ kind: "chordTone", role: bassRole });
|
|
2534
2667
|
handled = true;
|
|
@@ -2537,15 +2670,14 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2537
2670
|
}
|
|
2538
2671
|
if (!handled && chord && prev && next) {
|
|
2539
2672
|
const prevChord = chordAtBeat2(prev.startBeat);
|
|
2540
|
-
const prepared = prev.pitch === note.pitch &&
|
|
2673
|
+
const prepared = prev.pitch === note.pitch && _chunkYDGMWH43cjs.isChordMember.call(void 0, prev.pitch, prevChord);
|
|
2541
2674
|
const resolves = isStep(next.pitch, note.pitch);
|
|
2542
2675
|
const others = otherVoicesAtBeat(note.startBeat);
|
|
2543
|
-
const verticallyDissonant = others.some(
|
|
2544
|
-
(ov) => _chunk3R3QVKY5cjs.createsVerticalDissonance.call(void 0, note.pitch, ov.pitch, true)
|
|
2545
|
-
);
|
|
2676
|
+
const verticallyDissonant = others.length > 0 ? others.some((ov) => _chunkYDGMWH43cjs.createsVerticalDissonance.call(void 0, note.pitch, ov.pitch, true)) : clashesWithChord(note.pitch, chord);
|
|
2546
2677
|
if (prepared && verticallyDissonant && resolves) {
|
|
2547
2678
|
const ic = intervalAboveBass(note.pitch, others, chord);
|
|
2548
|
-
const
|
|
2679
|
+
const resolvedIc = intervalAboveBass(next.pitch, others, chord);
|
|
2680
|
+
const type = suspensionType(ic, next.pitch - note.pitch, resolvedIc);
|
|
2549
2681
|
if (type !== null) {
|
|
2550
2682
|
labels.push({ kind: "suspension", type, resolveTo: next.pitch });
|
|
2551
2683
|
handled = true;
|
|
@@ -2553,8 +2685,8 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2553
2685
|
}
|
|
2554
2686
|
}
|
|
2555
2687
|
if (!handled && chord && prev && next) {
|
|
2556
|
-
const prevMember =
|
|
2557
|
-
const nextMember =
|
|
2688
|
+
const prevMember = _chunkYDGMWH43cjs.isChordMember.call(void 0, prev.pitch, chordAtBeat2(prev.startBeat));
|
|
2689
|
+
const nextMember = _chunkYDGMWH43cjs.isChordMember.call(void 0, next.pitch, chordAtBeat2(next.startBeat));
|
|
2558
2690
|
const up = note.pitch - prev.pitch > 0;
|
|
2559
2691
|
const contInto = next.pitch - note.pitch > 0;
|
|
2560
2692
|
const sameDir = note.pitch !== prev.pitch && next.pitch !== note.pitch && up === contInto;
|
|
@@ -2563,20 +2695,20 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2563
2695
|
handled = true;
|
|
2564
2696
|
}
|
|
2565
2697
|
}
|
|
2566
|
-
if (!handled && chord && prev && next && !member && prev.pitch === next.pitch &&
|
|
2698
|
+
if (!handled && chord && prev && next && !member && prev.pitch === next.pitch && _chunkYDGMWH43cjs.isChordMember.call(void 0, prev.pitch, chordAtBeat2(prev.startBeat)) && isStep(note.pitch, prev.pitch)) {
|
|
2567
2699
|
labels.push({ kind: "neighbor" });
|
|
2568
2700
|
handled = true;
|
|
2569
2701
|
}
|
|
2570
2702
|
if (!handled && chord && next && !member && note.pitch === next.pitch) {
|
|
2571
2703
|
const nextChord = chordAtBeat2(next.startBeat);
|
|
2572
|
-
if (
|
|
2704
|
+
if (_chunkYDGMWH43cjs.isChordMember.call(void 0, next.pitch, nextChord)) {
|
|
2573
2705
|
labels.push({ kind: "anticipation" });
|
|
2574
2706
|
handled = true;
|
|
2575
2707
|
}
|
|
2576
2708
|
}
|
|
2577
2709
|
if (!handled && chord && prev && next && !member) {
|
|
2578
|
-
const prevMember =
|
|
2579
|
-
const nextMember =
|
|
2710
|
+
const prevMember = _chunkYDGMWH43cjs.isChordMember.call(void 0, prev.pitch, chordAtBeat2(prev.startBeat));
|
|
2711
|
+
const nextMember = _chunkYDGMWH43cjs.isChordMember.call(void 0, next.pitch, chordAtBeat2(next.startBeat));
|
|
2580
2712
|
const leapFromPrev = Math.abs(note.pitch - prev.pitch) >= LEAP_SEMITONES;
|
|
2581
2713
|
const stepToNext = isStep(next.pitch, note.pitch);
|
|
2582
2714
|
const opposite = note.pitch - prev.pitch > 0 !== next.pitch - note.pitch > 0;
|
|
@@ -2586,8 +2718,8 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2586
2718
|
}
|
|
2587
2719
|
}
|
|
2588
2720
|
if (!handled && chord && prev && next && !member) {
|
|
2589
|
-
const prevMember =
|
|
2590
|
-
const nextMember =
|
|
2721
|
+
const prevMember = _chunkYDGMWH43cjs.isChordMember.call(void 0, prev.pitch, chordAtBeat2(prev.startBeat));
|
|
2722
|
+
const nextMember = _chunkYDGMWH43cjs.isChordMember.call(void 0, next.pitch, chordAtBeat2(next.startBeat));
|
|
2591
2723
|
const stepFromPrev = isStep(note.pitch, prev.pitch);
|
|
2592
2724
|
const leapToNext = Math.abs(next.pitch - note.pitch) >= LEAP_SEMITONES;
|
|
2593
2725
|
const opposite = note.pitch - prev.pitch > 0 !== next.pitch - note.pitch > 0;
|
|
@@ -2597,7 +2729,7 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2597
2729
|
}
|
|
2598
2730
|
}
|
|
2599
2731
|
if (!handled && chord && !member) {
|
|
2600
|
-
const ic =
|
|
2732
|
+
const ic = _chunkYDGMWH43cjs.intervalAboveRoot.call(void 0, note.pitch, chord);
|
|
2601
2733
|
const degree = tensionDegree(ic);
|
|
2602
2734
|
const colours = NATURAL_TENSION_INTERVALS.has(ic) || chord.intervals.some((i2) => i2 === 10 || i2 === 11);
|
|
2603
2735
|
const avoid = ic === 5 && chord.intervals.includes(4) && !chord.intervals.includes(5) || ic === 11 && chord.intervals.includes(4) && chord.intervals.includes(10);
|
|
@@ -2616,7 +2748,7 @@ function analyzeVoice(voice, chordAtBeat2, key, otherVoicesAtBeat = () => []) {
|
|
|
2616
2748
|
);
|
|
2617
2749
|
}
|
|
2618
2750
|
}
|
|
2619
|
-
if (next &&
|
|
2751
|
+
if (next && _chunkYDGMWH43cjs.isLeadingToneResolution.call(void 0, note.pitch, next.pitch, keyAt(next.startBeat))) {
|
|
2620
2752
|
labels.push({ kind: "leadingTone", resolveTo: next.pitch });
|
|
2621
2753
|
}
|
|
2622
2754
|
const analyzed = {
|
|
@@ -2667,23 +2799,49 @@ function describe(labels) {
|
|
|
2667
2799
|
|
|
2668
2800
|
// src/analyze/timeline/index.ts
|
|
2669
2801
|
function assertChordTimeline(timeline, name = "timeline") {
|
|
2670
|
-
const read =
|
|
2671
|
-
|
|
2672
|
-
const segments =
|
|
2802
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, timeline, name);
|
|
2803
|
+
_chunkS3QELJUEcjs.assertFunction.call(void 0, read.at, `${name}.at`);
|
|
2804
|
+
const segments = _chunkS3QELJUEcjs.assertArray.call(void 0, read.segments, `${name}.segments`);
|
|
2673
2805
|
for (let index = 0; index < segments.length; index += 1) {
|
|
2674
|
-
const segment =
|
|
2675
|
-
|
|
2676
|
-
|
|
2806
|
+
const segment = _chunkS3QELJUEcjs.assertRecord.call(void 0, segments[index], `${name}.segments[${index}]`);
|
|
2807
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, segment.startBeat, `${name}.segments[${index}].startBeat`);
|
|
2808
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, segment.endBeat, `${name}.segments[${index}].endBeat`);
|
|
2677
2809
|
}
|
|
2810
|
+
assertSpansInOrder(segments, `${name}.segments`);
|
|
2678
2811
|
return read;
|
|
2679
2812
|
}
|
|
2813
|
+
function assertSpansInOrder(spans, name) {
|
|
2814
|
+
for (let index = 0; index < spans.length; index += 1) {
|
|
2815
|
+
const span = spans[index];
|
|
2816
|
+
if (span === void 0) {
|
|
2817
|
+
continue;
|
|
2818
|
+
}
|
|
2819
|
+
if (!(span.endBeat > span.startBeat)) {
|
|
2820
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
2821
|
+
`${name}[${index}] must end after it starts; received [${span.startBeat}, ${span.endBeat})`
|
|
2822
|
+
);
|
|
2823
|
+
}
|
|
2824
|
+
const previous = spans[index - 1];
|
|
2825
|
+
if (previous !== void 0 && span.startBeat < previous.endBeat) {
|
|
2826
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
2827
|
+
`${name}[${index}] must not start before ${name}[${index - 1}] ends; received ${span.startBeat} before ${previous.endBeat}`
|
|
2828
|
+
);
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
function statedKeyRegions(key, startBeat, endBeat) {
|
|
2833
|
+
if (!(endBeat > startBeat)) {
|
|
2834
|
+
return [];
|
|
2835
|
+
}
|
|
2836
|
+
return [{ startBeat, endBeat, key, confidence: 1 }];
|
|
2837
|
+
}
|
|
2680
2838
|
function chordTimelineFromChords(chords, totalBeats) {
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2839
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, totalBeats, 0, Number.MAX_SAFE_INTEGER, "timeline totalBeats");
|
|
2840
|
+
_chunkS3QELJUEcjs.assertArray.call(void 0, chords, "chords");
|
|
2841
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, chords.length, "timeline chords");
|
|
2684
2842
|
for (let index = 0; index < chords.length; index += 1) {
|
|
2685
|
-
|
|
2686
|
-
_nullishCoalesce(_optionalChain([chords, 'access',
|
|
2843
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0,
|
|
2844
|
+
_nullishCoalesce(_optionalChain([chords, 'access', _44 => _44[index], 'optionalAccess', _45 => _45.startBeat]), () => ( Number.NaN)),
|
|
2687
2845
|
-Number.MAX_SAFE_INTEGER,
|
|
2688
2846
|
Number.MAX_SAFE_INTEGER,
|
|
2689
2847
|
`chords[${index}].startBeat`
|
|
@@ -2697,13 +2855,13 @@ function chordTimelineFromChords(chords, totalBeats) {
|
|
|
2697
2855
|
return {
|
|
2698
2856
|
startBeat: gc.startBeat,
|
|
2699
2857
|
endBeat,
|
|
2700
|
-
chord:
|
|
2858
|
+
chord: _chunkYDGMWH43cjs.chordFromSpan.call(void 0, gc)
|
|
2701
2859
|
};
|
|
2702
2860
|
}).filter((seg) => seg.endBeat > seg.startBeat);
|
|
2703
2861
|
return { at: segmentLookup(segments), segments };
|
|
2704
2862
|
}
|
|
2705
2863
|
function chordAtBeat(segments, beat) {
|
|
2706
|
-
|
|
2864
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, beat, "timeline query beat");
|
|
2707
2865
|
const candidate = segments[firstAfter(segments, beat) - 1];
|
|
2708
2866
|
return candidate !== void 0 && beat >= candidate.startBeat && beat < candidate.endBeat ? candidate.chord : null;
|
|
2709
2867
|
}
|
|
@@ -2712,7 +2870,7 @@ function firstAfter(segments, beat) {
|
|
|
2712
2870
|
let high = segments.length;
|
|
2713
2871
|
while (low < high) {
|
|
2714
2872
|
const middle = Math.floor((low + high) / 2);
|
|
2715
|
-
if ((_nullishCoalesce(_optionalChain([segments, 'access',
|
|
2873
|
+
if ((_nullishCoalesce(_optionalChain([segments, 'access', _46 => _46[middle], 'optionalAccess', _47 => _47.startBeat]), () => ( Number.POSITIVE_INFINITY))) <= beat) {
|
|
2716
2874
|
low = middle + 1;
|
|
2717
2875
|
} else {
|
|
2718
2876
|
high = middle;
|
|
@@ -2723,7 +2881,7 @@ function firstAfter(segments, beat) {
|
|
|
2723
2881
|
function segmentStartingAt(segments, beat) {
|
|
2724
2882
|
const index = firstAfter(segments, beat);
|
|
2725
2883
|
for (const candidate of [segments[index - 1], segments[index]]) {
|
|
2726
|
-
if (candidate !== void 0 && Math.abs(candidate.startBeat - beat) <
|
|
2884
|
+
if (candidate !== void 0 && Math.abs(candidate.startBeat - beat) < _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2727
2885
|
return candidate;
|
|
2728
2886
|
}
|
|
2729
2887
|
}
|
|
@@ -2741,13 +2899,14 @@ var EXTRA_TONE_PENALTY = 0.6;
|
|
|
2741
2899
|
var OMITTED_TONE_PENALTY = 0.15;
|
|
2742
2900
|
var BASS_ROOT_STANDING = 0.95;
|
|
2743
2901
|
var OCTAVE = 12;
|
|
2902
|
+
var CHORD_SEGMENTATIONS = ["dynamic", "grid"];
|
|
2744
2903
|
function scoreMatch(match, weights, maxWeight, key, pedalPc) {
|
|
2745
2904
|
const rootWeight = maxWeight > 0 ? (_nullishCoalesce(weights[match.rootPc], () => ( 0))) / maxWeight : 0;
|
|
2746
2905
|
const rootStanding = match.inversion === 0 ? Math.max(rootWeight, BASS_ROOT_STANDING) : rootWeight;
|
|
2747
|
-
const chord =
|
|
2906
|
+
const chord = _chunkYDGMWH43cjs.makeChord.call(void 0, match.rootPc, match.quality);
|
|
2748
2907
|
const account = matchAccount(match, chord, pedalPc);
|
|
2749
2908
|
let score = rootStanding;
|
|
2750
|
-
if (
|
|
2909
|
+
if (_chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord).every((pc) => _chunkYDGMWH43cjs.isScaleTone.call(void 0, pc, key))) {
|
|
2751
2910
|
score += DIATONIC_BONUS;
|
|
2752
2911
|
}
|
|
2753
2912
|
if (account.exact) {
|
|
@@ -2757,12 +2916,15 @@ function scoreMatch(match, weights, maxWeight, key, pedalPc) {
|
|
|
2757
2916
|
score -= OMITTED_TONE_PENALTY * account.missing;
|
|
2758
2917
|
return score;
|
|
2759
2918
|
}
|
|
2760
|
-
var
|
|
2919
|
+
var SLASH_UPPER_QUALITY_LIST = ["maj", "min"];
|
|
2920
|
+
var SLASH_UPPER_QUALITIES = new Set(
|
|
2921
|
+
SLASH_UPPER_QUALITY_LIST
|
|
2922
|
+
);
|
|
2761
2923
|
function isSlashReading(match, pedalPc) {
|
|
2762
2924
|
return pedalPc !== null && match.inversion === null && match.missingPcs.length === 0 && match.extraPcs.length === 1 && match.extraPcs[0] === pedalPc && SLASH_UPPER_QUALITIES.has(match.quality);
|
|
2763
2925
|
}
|
|
2764
2926
|
function namesAsExtension(chord, pc) {
|
|
2765
|
-
return chord.intervals.some((iv) => iv >= OCTAVE &&
|
|
2927
|
+
return chord.intervals.some((iv) => iv >= OCTAVE && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc + iv) === pc);
|
|
2766
2928
|
}
|
|
2767
2929
|
function matchAccount(match, chord, pedalPc) {
|
|
2768
2930
|
const unvoiced = pedalPc !== null && namesAsExtension(chord, pedalPc) ? 1 : 0;
|
|
@@ -2778,10 +2940,10 @@ function bassSoundsOnlyBelow(notes, windowStart, windowEnd, bassPc) {
|
|
|
2778
2940
|
let highestBass = Number.NEGATIVE_INFINITY;
|
|
2779
2941
|
for (const note of notes) {
|
|
2780
2942
|
const overlap = Math.min(note.startBeat + note.durationBeat, windowEnd) - Math.max(note.startBeat, windowStart);
|
|
2781
|
-
if (overlap <=
|
|
2943
|
+
if (overlap <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2782
2944
|
continue;
|
|
2783
2945
|
}
|
|
2784
|
-
if (
|
|
2946
|
+
if (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, note.pitch) === bassPc) {
|
|
2785
2947
|
highestBass = Math.max(highestBass, note.pitch);
|
|
2786
2948
|
} else {
|
|
2787
2949
|
upperFloor = Math.min(upperFloor, note.pitch);
|
|
@@ -2789,8 +2951,32 @@ function bassSoundsOnlyBelow(notes, windowStart, windowEnd, bassPc) {
|
|
|
2789
2951
|
}
|
|
2790
2952
|
return highestBass <= upperFloor;
|
|
2791
2953
|
}
|
|
2954
|
+
function windowBass(notes, windowStart, windowEnd, meters, harmonicRhythm) {
|
|
2955
|
+
const counted = [];
|
|
2956
|
+
let firstSounding = Number.POSITIVE_INFINITY;
|
|
2957
|
+
for (const note of notes) {
|
|
2958
|
+
const overlap = Math.min(note.startBeat + note.durationBeat, windowEnd) - Math.max(note.startBeat, windowStart);
|
|
2959
|
+
if (overlap <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2960
|
+
continue;
|
|
2961
|
+
}
|
|
2962
|
+
const onsetInWindow = note.startBeat >= windowStart - _chunkS3QELJUEcjs.BEAT_EPS && note.startBeat < windowEnd - _chunkS3QELJUEcjs.BEAT_EPS;
|
|
2963
|
+
if (noteWeight(note, overlap, onsetInWindow ? meters : void 0) <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2964
|
+
continue;
|
|
2965
|
+
}
|
|
2966
|
+
counted.push({ note, overlap });
|
|
2967
|
+
firstSounding = Math.min(firstSounding, Math.max(note.startBeat, windowStart));
|
|
2968
|
+
}
|
|
2969
|
+
const half = (windowEnd - windowStart) / 2;
|
|
2970
|
+
let bass = Number.POSITIVE_INFINITY;
|
|
2971
|
+
for (const { note, overlap } of counted) {
|
|
2972
|
+
if (note.startBeat <= firstSounding + _chunkS3QELJUEcjs.BEAT_EPS || overlap > half || overlap >= harmonicRhythm - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2973
|
+
bass = Math.min(bass, note.pitch);
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
return bass;
|
|
2977
|
+
}
|
|
2792
2978
|
function chordConfidence(chord, weights, totalWeight, exact) {
|
|
2793
|
-
const tones = new Set(
|
|
2979
|
+
const tones = new Set(_chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord));
|
|
2794
2980
|
let chordWeight = 0;
|
|
2795
2981
|
for (let pc = 0; pc < 12; pc += 1) {
|
|
2796
2982
|
if (tones.has(pc)) {
|
|
@@ -2801,43 +2987,56 @@ function chordConfidence(chord, weights, totalWeight, exact) {
|
|
|
2801
2987
|
const confidence = Math.min(1, Math.max(0, raw));
|
|
2802
2988
|
return exact ? confidence : confidence * INEXACT_CONFIDENCE_FACTOR;
|
|
2803
2989
|
}
|
|
2804
|
-
function analyzeWindow(notes, windowStart, windowEnd, meters, key) {
|
|
2805
|
-
const { weights, totalWeight, maxWeight
|
|
2806
|
-
|
|
2807
|
-
windowStart,
|
|
2808
|
-
windowEnd,
|
|
2809
|
-
meters
|
|
2810
|
-
);
|
|
2811
|
-
if (totalWeight <= _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
2990
|
+
function analyzeWindow(notes, windowStart, windowEnd, meters, key, harmonicRhythm) {
|
|
2991
|
+
const { weights, totalWeight, maxWeight } = windowWeights(notes, windowStart, windowEnd, meters);
|
|
2992
|
+
if (totalWeight <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2812
2993
|
return null;
|
|
2813
2994
|
}
|
|
2814
2995
|
const ranked = weights.map((weight, pc) => ({ pc, weight })).filter(({ weight }) => weight > 0).sort((a, b) => b.weight - a.weight || a.pc - b.pc);
|
|
2815
|
-
const
|
|
2816
|
-
const
|
|
2817
|
-
const
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2996
|
+
const bassPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, windowBass(notes, windowStart, windowEnd, meters, harmonicRhythm));
|
|
2997
|
+
const sounding = ranked.slice(0, MAX_DETECTION_PCS).map(({ pc }) => pc);
|
|
2998
|
+
const significant = ranked.filter(({ weight }) => weight >= maxWeight * NOISE_THRESHOLD_RATIO).slice(0, MAX_DETECTION_PCS).map(({ pc }) => pc);
|
|
2999
|
+
let detection = detectWindow(significant, bassPc, notes, windowStart, windowEnd);
|
|
3000
|
+
if (detection.matches.length === 0 && significant.length < sounding.length) {
|
|
3001
|
+
detection = detectWindow(sounding, bassPc, notes, windowStart, windowEnd);
|
|
3002
|
+
}
|
|
3003
|
+
const { selected, hasBass, pedalPc, matches } = detection;
|
|
2821
3004
|
let bestMatch = null;
|
|
2822
3005
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
2823
3006
|
for (const match of matches) {
|
|
2824
|
-
const score = scoreMatch(match, weights, maxWeight,
|
|
3007
|
+
const score = scoreMatch(match, weights, maxWeight, _chunkYDGMWH43cjs.scaleOf.call(void 0, key), pedalPc);
|
|
2825
3008
|
if (score > bestScore) {
|
|
2826
3009
|
bestScore = score;
|
|
2827
3010
|
bestMatch = match;
|
|
2828
3011
|
}
|
|
2829
3012
|
}
|
|
2830
3013
|
if (bestMatch) {
|
|
2831
|
-
const chord =
|
|
3014
|
+
const chord = _chunkYDGMWH43cjs.makeChord.call(void 0, bestMatch.rootPc, bestMatch.quality, bestMatch.bassPc);
|
|
2832
3015
|
const account = matchAccount(
|
|
2833
3016
|
bestMatch,
|
|
2834
|
-
|
|
3017
|
+
_chunkYDGMWH43cjs.makeChord.call(void 0, bestMatch.rootPc, bestMatch.quality),
|
|
2835
3018
|
pedalPc
|
|
2836
3019
|
);
|
|
3020
|
+
const explained = account.exact || isSlashReading(bestMatch, pedalPc);
|
|
2837
3021
|
const reading = {
|
|
2838
3022
|
chord: shared(chord),
|
|
2839
|
-
confidence: chordConfidence(chord, weights, totalWeight,
|
|
3023
|
+
confidence: chordConfidence(chord, weights, totalWeight, explained)
|
|
2840
3024
|
};
|
|
3025
|
+
if (bestMatch.quality === SYMMETRIC_QUALITY) {
|
|
3026
|
+
reading.rootings = _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, bestMatch.rootPc, bestMatch.quality)).map(
|
|
3027
|
+
(rootPc) => {
|
|
3028
|
+
const rooted = _chunkYDGMWH43cjs.makeChord.call(void 0,
|
|
3029
|
+
rootPc,
|
|
3030
|
+
bestMatch.quality,
|
|
3031
|
+
hasBass && bassPc !== rootPc ? bassPc : void 0
|
|
3032
|
+
);
|
|
3033
|
+
return {
|
|
3034
|
+
chord: shared(rooted),
|
|
3035
|
+
confidence: chordConfidence(rooted, weights, totalWeight, explained)
|
|
3036
|
+
};
|
|
3037
|
+
}
|
|
3038
|
+
);
|
|
3039
|
+
}
|
|
2841
3040
|
const augmented = hasBass ? augmentedSixthFromPitchClasses(selected, bassPc, key) : null;
|
|
2842
3041
|
if (augmented !== null) {
|
|
2843
3042
|
reading.augmented = {
|
|
@@ -2849,14 +3048,21 @@ function analyzeWindow(notes, windowStart, windowEnd, meters, key) {
|
|
|
2849
3048
|
}
|
|
2850
3049
|
return null;
|
|
2851
3050
|
}
|
|
3051
|
+
function detectWindow(selected, bassPc, notes, windowStart, windowEnd) {
|
|
3052
|
+
const hasBass = selected.includes(bassPc);
|
|
3053
|
+
const detectionPitches = hasBass ? selected.map((pc) => pc === bassPc ? pc : pc + 12) : selected;
|
|
3054
|
+
const pedalPc = hasBass && bassSoundsOnlyBelow(notes, windowStart, windowEnd, bassPc) ? bassPc : null;
|
|
3055
|
+
const matches = detectChord(detectionPitches, { input: hasBass ? "midi" : "pitchClass" });
|
|
3056
|
+
return { selected, hasBass, pedalPc, matches };
|
|
3057
|
+
}
|
|
2852
3058
|
function shared(chord) {
|
|
2853
3059
|
Object.freeze(chord.intervals);
|
|
2854
3060
|
return Object.freeze(chord);
|
|
2855
3061
|
}
|
|
2856
3062
|
var DOMINANT_ABOVE_TONIC = 7;
|
|
2857
3063
|
function resolvesOntoDominant(readings, index, key) {
|
|
2858
|
-
const dominantPc =
|
|
2859
|
-
const candidate = _optionalChain([readings, 'access',
|
|
3064
|
+
const dominantPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc + DOMINANT_ABOVE_TONIC);
|
|
3065
|
+
const candidate = _optionalChain([readings, 'access', _48 => _48[index], 'optionalAccess', _49 => _49.chord]);
|
|
2860
3066
|
for (let i = index + 1; i < readings.length; i += 1) {
|
|
2861
3067
|
const next = readings[i];
|
|
2862
3068
|
if (!next) {
|
|
@@ -2866,15 +3072,38 @@ function resolvesOntoDominant(readings, index, key) {
|
|
|
2866
3072
|
if (candidate !== void 0 && sameChord(chord, candidate)) {
|
|
2867
3073
|
continue;
|
|
2868
3074
|
}
|
|
2869
|
-
if (
|
|
3075
|
+
if (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, _nullishCoalesce(chord.bassPc, () => ( chord.rootPc))) !== dominantPc) {
|
|
2870
3076
|
return false;
|
|
2871
3077
|
}
|
|
2872
|
-
if (
|
|
3078
|
+
if (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc) === dominantPc) {
|
|
2873
3079
|
return true;
|
|
2874
3080
|
}
|
|
2875
3081
|
}
|
|
2876
3082
|
return true;
|
|
2877
3083
|
}
|
|
3084
|
+
var SYMMETRIC_QUALITY = "dim7";
|
|
3085
|
+
function settledDiminishedRoot(readings, index, key) {
|
|
3086
|
+
const reading = readings[index];
|
|
3087
|
+
const rootings = _optionalChain([reading, 'optionalAccess', _50 => _50.rootings]);
|
|
3088
|
+
if (!reading || rootings === void 0) {
|
|
3089
|
+
return null;
|
|
3090
|
+
}
|
|
3091
|
+
const roots = rootings.map((rooting) => rooting.chord.rootPc);
|
|
3092
|
+
const tones = _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, reading.chord).join();
|
|
3093
|
+
for (let i = index + 1; i < readings.length; i += 1) {
|
|
3094
|
+
const next = readings[i];
|
|
3095
|
+
if (!next || _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, next.chord).join() === tones) {
|
|
3096
|
+
continue;
|
|
3097
|
+
}
|
|
3098
|
+
const leading = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, next.chord.rootPc - 1);
|
|
3099
|
+
if (roots.includes(leading)) {
|
|
3100
|
+
return leading;
|
|
3101
|
+
}
|
|
3102
|
+
break;
|
|
3103
|
+
}
|
|
3104
|
+
const leadingTone = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc - 1);
|
|
3105
|
+
return roots.includes(leadingTone) ? leadingTone : null;
|
|
3106
|
+
}
|
|
2878
3107
|
function sameChord(a, b) {
|
|
2879
3108
|
return a.rootPc === b.rootPc && a.quality === b.quality && a.bassPc === b.bassPc;
|
|
2880
3109
|
}
|
|
@@ -2902,7 +3131,7 @@ var LEXICON_TONES = (() => {
|
|
|
2902
3131
|
for (const quality of SEGMENTATION_QUALITIES) {
|
|
2903
3132
|
LEXICON_ROOTS[candidate] = rootPc;
|
|
2904
3133
|
LEXICON_TONE_START[candidate] = tones.length;
|
|
2905
|
-
tones.push(...
|
|
3134
|
+
tones.push(..._chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, rootPc, quality)));
|
|
2906
3135
|
candidate += 1;
|
|
2907
3136
|
}
|
|
2908
3137
|
}
|
|
@@ -2923,7 +3152,7 @@ function candidateScore(candidate, weights, totalWeight) {
|
|
|
2923
3152
|
for (let index = first; index < last; index += 1) {
|
|
2924
3153
|
const weight = _nullishCoalesce(weights[_nullishCoalesce(LEXICON_TONES[index], () => ( 0))], () => ( 0));
|
|
2925
3154
|
covered += weight;
|
|
2926
|
-
if (weight <=
|
|
3155
|
+
if (weight <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2927
3156
|
missing += 1;
|
|
2928
3157
|
}
|
|
2929
3158
|
}
|
|
@@ -2939,16 +3168,16 @@ function slotOfBeat(grid, beat) {
|
|
|
2939
3168
|
}
|
|
2940
3169
|
function createBoundaryTables(slotCount, budget) {
|
|
2941
3170
|
return {
|
|
2942
|
-
scores:
|
|
2943
|
-
back:
|
|
2944
|
-
costs:
|
|
2945
|
-
spare:
|
|
2946
|
-
path:
|
|
3171
|
+
scores: _chunkS3QELJUEcjs.allocateCandidateTable.call(void 0, slotCount, LEXICON_SIZE, "timeline window scores", budget),
|
|
3172
|
+
back: _chunkS3QELJUEcjs.allocateChoiceTable.call(void 0, slotCount, LEXICON_SIZE, "timeline window choices", budget),
|
|
3173
|
+
costs: _chunkS3QELJUEcjs.allocateCandidateTable.call(void 0, 1, LEXICON_SIZE, "timeline window costs", budget),
|
|
3174
|
+
spare: _chunkS3QELJUEcjs.allocateCandidateTable.call(void 0, 1, LEXICON_SIZE, "timeline window costs", budget),
|
|
3175
|
+
path: _chunkS3QELJUEcjs.allocateChoiceTable.call(void 0, slotCount, 1, "timeline window path", budget)
|
|
2947
3176
|
};
|
|
2948
3177
|
}
|
|
2949
3178
|
function scoreSlot(tables, slot, index) {
|
|
2950
3179
|
const base = index * LEXICON_SIZE;
|
|
2951
|
-
if (slot.totalWeight <=
|
|
3180
|
+
if (slot.totalWeight <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
2952
3181
|
tables.scores.fill(0, base, base + LEXICON_SIZE);
|
|
2953
3182
|
return;
|
|
2954
3183
|
}
|
|
@@ -2978,7 +3207,7 @@ function chooseBoundaries(tables, from, to, grid, meters, changeCost) {
|
|
|
2978
3207
|
}
|
|
2979
3208
|
}
|
|
2980
3209
|
const slotStart = beatOfSlot(grid, from + i);
|
|
2981
|
-
const accent =
|
|
3210
|
+
const accent = _chunkS3QELJUEcjs.metricWeight.call(void 0, slotStart, meters);
|
|
2982
3211
|
const penalty = changeCost * (1 - STRONG_BEAT_DISCOUNT2 * accent / MAX_METRIC_WEIGHT2);
|
|
2983
3212
|
const rowBase = (from + i) * LEXICON_SIZE;
|
|
2984
3213
|
const change = cheapest + penalty;
|
|
@@ -3020,7 +3249,7 @@ function chooseBoundaries(tables, from, to, grid, meters, changeCost) {
|
|
|
3020
3249
|
}
|
|
3021
3250
|
function slotBeatsWithin(gridUnit, minChordBeats, harmonicRhythm) {
|
|
3022
3251
|
const resolution = Math.min(minChordBeats, harmonicRhythm);
|
|
3023
|
-
const divisions = Math.max(1, Math.ceil(gridUnit / resolution -
|
|
3252
|
+
const divisions = Math.max(1, Math.ceil(gridUnit / resolution - _chunkS3QELJUEcjs.BEAT_EPS));
|
|
3024
3253
|
return gridUnit / divisions;
|
|
3025
3254
|
}
|
|
3026
3255
|
function gridSpans(slotCount, grid) {
|
|
@@ -3035,8 +3264,8 @@ function dynamicSpans(slotWeights, tables, grid, harmonicRhythm, meters) {
|
|
|
3035
3264
|
let soundingSlots = 0;
|
|
3036
3265
|
let weightSum = 0;
|
|
3037
3266
|
for (let i = 0; i < slotCount; i += 1) {
|
|
3038
|
-
const weight = _nullishCoalesce(_optionalChain([slotWeights, 'access',
|
|
3039
|
-
if (weight >
|
|
3267
|
+
const weight = _nullishCoalesce(_optionalChain([slotWeights, 'access', _51 => _51[i], 'optionalAccess', _52 => _52.totalWeight]), () => ( 0));
|
|
3268
|
+
if (weight > _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
3040
3269
|
soundingSlots += 1;
|
|
3041
3270
|
weightSum += weight;
|
|
3042
3271
|
}
|
|
@@ -3046,7 +3275,7 @@ function dynamicSpans(slotWeights, tables, grid, harmonicRhythm, meters) {
|
|
|
3046
3275
|
}
|
|
3047
3276
|
const meanSlotWeight = weightSum / soundingSlots;
|
|
3048
3277
|
const changeCost = CHANGE_COST * meanSlotWeight * (harmonicRhythm / slotBeats);
|
|
3049
|
-
const silent = slotWeights.map((slot) => slot.totalWeight <=
|
|
3278
|
+
const silent = slotWeights.map((slot) => slot.totalWeight <= _chunkS3QELJUEcjs.BEAT_EPS);
|
|
3050
3279
|
const breaks = new Array(slotCount).fill(false);
|
|
3051
3280
|
for (let i = 0; i < slotCount; ) {
|
|
3052
3281
|
if (!silent[i]) {
|
|
@@ -3057,7 +3286,7 @@ function dynamicSpans(slotWeights, tables, grid, harmonicRhythm, meters) {
|
|
|
3057
3286
|
while (end < slotCount && silent[end]) {
|
|
3058
3287
|
end += 1;
|
|
3059
3288
|
}
|
|
3060
|
-
if ((end - i) * slotBeats >= harmonicRhythm -
|
|
3289
|
+
if ((end - i) * slotBeats >= harmonicRhythm - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
3061
3290
|
for (let k = i; k < end; k += 1) {
|
|
3062
3291
|
breaks[k] = true;
|
|
3063
3292
|
}
|
|
@@ -3120,45 +3349,46 @@ function evidenceFits(previous, grid, slotCount, totalBeats, segmentation, harmo
|
|
|
3120
3349
|
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;
|
|
3121
3350
|
}
|
|
3122
3351
|
function analyzeTimeline(notes, opts = {}, previous, dirty) {
|
|
3123
|
-
const meters =
|
|
3124
|
-
const harmonicRhythm = _nullishCoalesce(opts.harmonicRhythm, () => (
|
|
3125
|
-
|
|
3126
|
-
const segmentation =
|
|
3127
|
-
|
|
3352
|
+
const meters = _chunkS3QELJUEcjs.resolveMeters.call(void 0, opts, "timeline meters");
|
|
3353
|
+
const harmonicRhythm = _nullishCoalesce(opts.harmonicRhythm, () => ( _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, 0, meters)));
|
|
3354
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, harmonicRhythm, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "harmonic rhythm");
|
|
3355
|
+
const segmentation = _chunkS3QELJUEcjs.assertOneOf.call(void 0,
|
|
3356
|
+
_nullishCoalesce(opts.segmentation, () => ( "dynamic")),
|
|
3357
|
+
CHORD_SEGMENTATIONS,
|
|
3358
|
+
"timeline segmentation"
|
|
3359
|
+
);
|
|
3360
|
+
const gridUnit = _chunkS3QELJUEcjs.metricGridUnit.call(void 0, meters);
|
|
3128
3361
|
const minChordBeats = _nullishCoalesce(opts.minChordBeats, () => ( gridUnit));
|
|
3129
|
-
|
|
3362
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, minChordBeats, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER, "minChordBeats");
|
|
3130
3363
|
const budget = opts.budget;
|
|
3131
3364
|
const noteOptions = { allowNonPositiveDuration: true, budget };
|
|
3132
3365
|
if (opts.pickupBeats !== void 0) {
|
|
3133
|
-
|
|
3366
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, opts.pickupBeats, 0, Number.MAX_SAFE_INTEGER, "timeline pickupBeats");
|
|
3134
3367
|
noteOptions.minStartBeat = -opts.pickupBeats;
|
|
3135
3368
|
}
|
|
3136
|
-
|
|
3137
|
-
const sounding =
|
|
3138
|
-
const
|
|
3139
|
-
|
|
3140
|
-
|
|
3369
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, notes, "timeline notes", noteOptions);
|
|
3370
|
+
const sounding = _chunkKMYGRFZ6cjs.sortedNoteEvents.call(void 0, notes.filter((note) => note.durationBeat > 0));
|
|
3371
|
+
const totalBeats = _nullishCoalesce(opts.totalBeats, () => ( latestSoundingEnd(sounding)));
|
|
3372
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0,
|
|
3373
|
+
totalBeats,
|
|
3374
|
+
Math.min(0, firstSoundingBeat(sounding)),
|
|
3375
|
+
Number.MAX_SAFE_INTEGER,
|
|
3376
|
+
"timeline totalBeats"
|
|
3377
|
+
);
|
|
3141
3378
|
const slotBeats = segmentation === "grid" ? harmonicRhythm : slotBeatsWithin(gridUnit, minChordBeats, harmonicRhythm);
|
|
3142
3379
|
const { origin, startBeat: musicStart } = gridForNotes(sounding, slotBeats);
|
|
3143
3380
|
const grid = { origin, slotBeats };
|
|
3144
|
-
const slotCount = Math.max(0, Math.ceil((totalBeats - grid.origin) / slotBeats -
|
|
3381
|
+
const slotCount = Math.max(0, Math.ceil((totalBeats - grid.origin) / slotBeats - _chunkS3QELJUEcjs.BEAT_EPS));
|
|
3145
3382
|
const dynamic = segmentation === "dynamic";
|
|
3146
|
-
|
|
3383
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0,
|
|
3147
3384
|
dynamic ? slotCount * LEXICON_SIZE : slotCount,
|
|
3148
3385
|
"timeline windows",
|
|
3149
3386
|
budget
|
|
3150
3387
|
);
|
|
3151
|
-
const keys = opts.key !== void 0 ?
|
|
3152
|
-
|
|
3153
|
-
startBeat: musicStart,
|
|
3154
|
-
endBeat: totalBeats,
|
|
3155
|
-
key: _chunk3R3QVKY5cjs.resolveKey.call(void 0, opts.key),
|
|
3156
|
-
confidence: 1
|
|
3157
|
-
}
|
|
3158
|
-
] : keyTimelineFromNotes(sounding, { meters, totalBeats, budget });
|
|
3159
|
-
const prevailingKey = _nullishCoalesce(prevailingKeyOf(keys), () => ( _chunk3R3QVKY5cjs.resolveKey.call(void 0, _chunk3R3QVKY5cjs.majorKey.call(void 0, 0))));
|
|
3388
|
+
const keys = opts.key !== void 0 ? statedKeyRegions(_chunkYDGMWH43cjs.resolveKey.call(void 0, opts.key), musicStart, totalBeats) : keyTimelineFromNotes(sounding, { meters, totalBeats, budget });
|
|
3389
|
+
const prevailingKey = _nullishCoalesce(prevailingKeyOf(keys), () => ( _chunkYDGMWH43cjs.resolveKey.call(void 0, _chunkYDGMWH43cjs.majorKey.call(void 0, 0))));
|
|
3160
3390
|
const keyAt = keyLookup(keys, prevailingKey);
|
|
3161
|
-
const scaleAt = (beat) =>
|
|
3391
|
+
const scaleAt = (beat) => _chunkYDGMWH43cjs.scaleOf.call(void 0, keyAt(beat));
|
|
3162
3392
|
const segments = [];
|
|
3163
3393
|
const segmentConfidence = [];
|
|
3164
3394
|
const slotNotes = bucketNotesBySlot(sounding, grid, slotCount, {
|
|
@@ -3174,15 +3404,15 @@ function analyzeTimeline(notes, opts = {}, previous, dirty) {
|
|
|
3174
3404
|
harmonicRhythm,
|
|
3175
3405
|
opts.key !== void 0
|
|
3176
3406
|
) ? previous : void 0;
|
|
3177
|
-
const dirtyFrom = carried === void 0 ? 0 : Math.max(0, _nullishCoalesce(_optionalChain([dirty, 'optionalAccess',
|
|
3178
|
-
const dirtyTo = carried === void 0 ? slotCount : Math.min(slotCount, _nullishCoalesce(_optionalChain([dirty, 'optionalAccess',
|
|
3179
|
-
const tables = _nullishCoalesce(_optionalChain([carried, 'optionalAccess',
|
|
3407
|
+
const dirtyFrom = carried === void 0 ? 0 : Math.max(0, _nullishCoalesce(_optionalChain([dirty, 'optionalAccess', _53 => _53.from]), () => ( 0)));
|
|
3408
|
+
const dirtyTo = carried === void 0 ? slotCount : Math.min(slotCount, _nullishCoalesce(_optionalChain([dirty, 'optionalAccess', _54 => _54.to]), () => ( slotCount)));
|
|
3409
|
+
const tables = _nullishCoalesce(_optionalChain([carried, 'optionalAccess', _55 => _55.tables]), () => ( createBoundaryTables(dynamic ? slotCount : 0, budget)));
|
|
3180
3410
|
if (carried !== void 0) {
|
|
3181
3411
|
carried.tables = void 0;
|
|
3182
3412
|
}
|
|
3183
3413
|
const slotWeights = new Array(slotCount);
|
|
3184
3414
|
for (let i = 0; i < slotCount; i += 1) {
|
|
3185
|
-
const reusable = i < dirtyFrom || i >= dirtyTo ? _optionalChain([carried, 'optionalAccess',
|
|
3415
|
+
const reusable = i < dirtyFrom || i >= dirtyTo ? _optionalChain([carried, 'optionalAccess', _56 => _56.slotWeights, 'access', _57 => _57[i]]) : void 0;
|
|
3186
3416
|
if (reusable !== void 0) {
|
|
3187
3417
|
slotWeights[i] = reusable;
|
|
3188
3418
|
continue;
|
|
@@ -3211,14 +3441,29 @@ function analyzeTimeline(notes, opts = {}, previous, dirty) {
|
|
|
3211
3441
|
const spanKeyWhole = keyAt(start);
|
|
3212
3442
|
const id = windowId(start, end, spanKey);
|
|
3213
3443
|
const cached = carried !== void 0 && spanIsClean(grid, span, dirtyFrom, dirtyTo) ? carried.windows.get(id) : void 0;
|
|
3214
|
-
const inferred = cached !== void 0 ? cached : analyzeWindow(
|
|
3444
|
+
const inferred = cached !== void 0 ? cached : analyzeWindow(
|
|
3445
|
+
notesOfSpan(slotNotes, span, grid),
|
|
3446
|
+
start,
|
|
3447
|
+
end,
|
|
3448
|
+
meters,
|
|
3449
|
+
spanKeyWhole,
|
|
3450
|
+
harmonicRhythm
|
|
3451
|
+
);
|
|
3215
3452
|
windows.set(id, inferred);
|
|
3216
3453
|
readings.push(inferred);
|
|
3217
3454
|
readingKeys.push(spanKey);
|
|
3218
3455
|
readingBounds.push({ start, end });
|
|
3219
3456
|
}
|
|
3457
|
+
for (let i = readings.length - 1; i >= 0; i -= 1) {
|
|
3458
|
+
const spanKey = readingKeys[i];
|
|
3459
|
+
const root = spanKey === void 0 ? null : settledDiminishedRoot(readings, i, spanKey);
|
|
3460
|
+
const rooting = _optionalChain([readings, 'access', _58 => _58[i], 'optionalAccess', _59 => _59.rootings, 'optionalAccess', _60 => _60.find, 'call', _61 => _61((option) => option.chord.rootPc === root)]);
|
|
3461
|
+
if (rooting !== void 0 && root !== _optionalChain([readings, 'access', _62 => _62[i], 'optionalAccess', _63 => _63.chord, 'access', _64 => _64.rootPc])) {
|
|
3462
|
+
readings[i] = rooting;
|
|
3463
|
+
}
|
|
3464
|
+
}
|
|
3220
3465
|
for (let i = 0; i < readings.length; i += 1) {
|
|
3221
|
-
const offered = _optionalChain([readings, 'access',
|
|
3466
|
+
const offered = _optionalChain([readings, 'access', _65 => _65[i], 'optionalAccess', _66 => _66.augmented]);
|
|
3222
3467
|
const spanKey = readingKeys[i];
|
|
3223
3468
|
if (offered !== void 0 && spanKey !== void 0 && resolvesOntoDominant(readings, i, spanKey)) {
|
|
3224
3469
|
readings[i] = offered;
|
|
@@ -3232,7 +3477,7 @@ function analyzeTimeline(notes, opts = {}, previous, dirty) {
|
|
|
3232
3477
|
}
|
|
3233
3478
|
const { start, end } = bounds;
|
|
3234
3479
|
const last = segments[segments.length - 1];
|
|
3235
|
-
if (last && sameChord(last.chord, inferred.chord) && Math.abs(last.endBeat - start) <
|
|
3480
|
+
if (last && sameChord(last.chord, inferred.chord) && Math.abs(last.endBeat - start) < _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
3236
3481
|
const lastLength = last.endBeat - last.startBeat;
|
|
3237
3482
|
const length = end - start;
|
|
3238
3483
|
const lastConfidence = _nullishCoalesce(segmentConfidence[segmentConfidence.length - 1], () => ( 0));
|
|
@@ -3273,11 +3518,11 @@ function detectCadences(timeline, key) {
|
|
|
3273
3518
|
if (!prev || !cur) {
|
|
3274
3519
|
continue;
|
|
3275
3520
|
}
|
|
3276
|
-
if (Math.abs(cur.startBeat - prev.endBeat) >
|
|
3521
|
+
if (Math.abs(cur.startBeat - prev.endBeat) > _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
3277
3522
|
continue;
|
|
3278
3523
|
}
|
|
3279
3524
|
const before = timeline.segments[i - 2];
|
|
3280
|
-
const approach = before !== void 0 && Math.abs(prev.startBeat - before.endBeat) <=
|
|
3525
|
+
const approach = before !== void 0 && Math.abs(prev.startBeat - before.endBeat) <= _chunkS3QELJUEcjs.BEAT_EPS ? before.chord : void 0;
|
|
3281
3526
|
const key2 = keyAt(cur.startBeat);
|
|
3282
3527
|
const cadence = detectCadence(prev.chord, cur.chord, key2, {
|
|
3283
3528
|
...approach === void 0 ? {} : { approach }
|
|
@@ -3287,7 +3532,7 @@ function detectCadences(timeline, key) {
|
|
|
3287
3532
|
}
|
|
3288
3533
|
if (cadence.type === "half" && isCadentialSixFour(prev.chord, cur.chord, key2)) {
|
|
3289
3534
|
const next = timeline.segments[i + 1];
|
|
3290
|
-
if (next !== void 0 && Math.abs(next.startBeat - cur.endBeat) <=
|
|
3535
|
+
if (next !== void 0 && Math.abs(next.startBeat - cur.endBeat) <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
3291
3536
|
const onward = detectCadence(cur.chord, next.chord, keyAt(next.startBeat)).type;
|
|
3292
3537
|
if (onward === "authentic" || onward === "deceptive") {
|
|
3293
3538
|
continue;
|
|
@@ -3305,15 +3550,15 @@ function phraseNotes(phrase) {
|
|
|
3305
3550
|
if (Array.isArray(phrase)) {
|
|
3306
3551
|
return phrase;
|
|
3307
3552
|
}
|
|
3308
|
-
return
|
|
3553
|
+
return _chunkS3QELJUEcjs.assertRecord.call(void 0, phrase, "melodic phrase").notes;
|
|
3309
3554
|
}
|
|
3310
3555
|
function orderedNotes(notes, name, budget) {
|
|
3311
|
-
|
|
3556
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, notes, name, { allowNonPositiveDuration: true, budget });
|
|
3312
3557
|
const sounding = notes.filter((note) => note.durationBeat > 0).sort((a, b) => a.startBeat - b.startBeat || a.pitch - b.pitch);
|
|
3313
3558
|
const line = [];
|
|
3314
3559
|
for (const note of sounding) {
|
|
3315
3560
|
const previous = line[line.length - 1];
|
|
3316
|
-
if (previous !== void 0 && Math.abs(note.startBeat - previous.startBeat) <=
|
|
3561
|
+
if (previous !== void 0 && Math.abs(note.startBeat - previous.startBeat) <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
3317
3562
|
line[line.length - 1] = note;
|
|
3318
3563
|
continue;
|
|
3319
3564
|
}
|
|
@@ -3324,14 +3569,14 @@ function orderedNotes(notes, name, budget) {
|
|
|
3324
3569
|
function intervalsOf(notes) {
|
|
3325
3570
|
const out = [];
|
|
3326
3571
|
for (let i = 1; i < notes.length; i += 1) {
|
|
3327
|
-
out.push((_nullishCoalesce(_optionalChain([notes, 'access',
|
|
3572
|
+
out.push((_nullishCoalesce(_optionalChain([notes, 'access', _67 => _67[i], 'optionalAccess', _68 => _68.pitch]), () => ( 0))) - (_nullishCoalesce(_optionalChain([notes, 'access', _69 => _69[i - 1], 'optionalAccess', _70 => _70.pitch]), () => ( 0))));
|
|
3328
3573
|
}
|
|
3329
3574
|
return out;
|
|
3330
3575
|
}
|
|
3331
3576
|
function onsetGaps(notes) {
|
|
3332
3577
|
const out = [];
|
|
3333
3578
|
for (let i = 1; i < notes.length; i += 1) {
|
|
3334
|
-
out.push((_nullishCoalesce(_optionalChain([notes, 'access',
|
|
3579
|
+
out.push((_nullishCoalesce(_optionalChain([notes, 'access', _71 => _71[i], 'optionalAccess', _72 => _72.startBeat]), () => ( 0))) - (_nullishCoalesce(_optionalChain([notes, 'access', _73 => _73[i - 1], 'optionalAccess', _74 => _74.startBeat]), () => ( 0))));
|
|
3335
3580
|
}
|
|
3336
3581
|
return out;
|
|
3337
3582
|
}
|
|
@@ -3341,14 +3586,14 @@ function retrogradeGaps(notes) {
|
|
|
3341
3586
|
const later = notes[i];
|
|
3342
3587
|
const earlier = notes[i - 1];
|
|
3343
3588
|
out.push(
|
|
3344
|
-
(_nullishCoalesce(_optionalChain([later, 'optionalAccess',
|
|
3589
|
+
(_nullishCoalesce(_optionalChain([later, 'optionalAccess', _75 => _75.startBeat]), () => ( 0))) + (_nullishCoalesce(_optionalChain([later, 'optionalAccess', _76 => _76.durationBeat]), () => ( 0))) - ((_nullishCoalesce(_optionalChain([earlier, 'optionalAccess', _77 => _77.startBeat]), () => ( 0))) + (_nullishCoalesce(_optionalChain([earlier, 'optionalAccess', _78 => _78.durationBeat]), () => ( 0))))
|
|
3345
3590
|
);
|
|
3346
3591
|
}
|
|
3347
3592
|
return out;
|
|
3348
3593
|
}
|
|
3349
3594
|
function rhythmProfile(gaps) {
|
|
3350
3595
|
const unit = _nullishCoalesce(gaps[0], () => ( 0));
|
|
3351
|
-
if (!(unit >
|
|
3596
|
+
if (!(unit > _chunkS3QELJUEcjs.BEAT_EPS)) {
|
|
3352
3597
|
return gaps.length === 0 ? [] : null;
|
|
3353
3598
|
}
|
|
3354
3599
|
return gaps.map((gap) => Math.round(gap / unit * RHYTHM_GRID) / RHYTHM_GRID);
|
|
@@ -3358,7 +3603,7 @@ function sameNumbers(a, b) {
|
|
|
3358
3603
|
return false;
|
|
3359
3604
|
}
|
|
3360
3605
|
for (let i = 0; i < a.length; i += 1) {
|
|
3361
|
-
if (Math.abs((_nullishCoalesce(a[i], () => ( 0))) - (_nullishCoalesce(b[i], () => ( 0)))) >
|
|
3606
|
+
if (Math.abs((_nullishCoalesce(a[i], () => ( 0))) - (_nullishCoalesce(b[i], () => ( 0)))) > _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
3362
3607
|
return false;
|
|
3363
3608
|
}
|
|
3364
3609
|
}
|
|
@@ -3369,17 +3614,13 @@ function roundTo(value, digits) {
|
|
|
3369
3614
|
return Math.round(value * scale) / scale;
|
|
3370
3615
|
}
|
|
3371
3616
|
function endBeatOf(notes) {
|
|
3372
|
-
|
|
3373
|
-
for (const note of notes) {
|
|
3374
|
-
end = Math.max(end, note.startBeat + note.durationBeat);
|
|
3375
|
-
}
|
|
3376
|
-
return end;
|
|
3617
|
+
return latestSoundingEnd(notes);
|
|
3377
3618
|
}
|
|
3378
3619
|
function onsetSpan(notes) {
|
|
3379
3620
|
if (notes.length < 2) {
|
|
3380
3621
|
return 0;
|
|
3381
3622
|
}
|
|
3382
|
-
return (_nullishCoalesce(_optionalChain([notes, 'access',
|
|
3623
|
+
return (_nullishCoalesce(_optionalChain([notes, 'access', _79 => _79[notes.length - 1], 'optionalAccess', _80 => _80.startBeat]), () => ( 0))) - (_nullishCoalesce(_optionalChain([notes, 'access', _81 => _81[0], 'optionalAccess', _82 => _82.startBeat]), () => ( 0)));
|
|
3383
3624
|
}
|
|
3384
3625
|
|
|
3385
3626
|
// src/analyze/melody/contour.ts
|
|
@@ -3398,10 +3639,10 @@ function extremes(notes) {
|
|
|
3398
3639
|
let peak = 0;
|
|
3399
3640
|
let trough = 0;
|
|
3400
3641
|
for (let i = 1; i < notes.length; i += 1) {
|
|
3401
|
-
if ((_nullishCoalesce(_optionalChain([notes, 'access',
|
|
3642
|
+
if ((_nullishCoalesce(_optionalChain([notes, 'access', _83 => _83[i], 'optionalAccess', _84 => _84.pitch]), () => ( 0))) > (_nullishCoalesce(_optionalChain([notes, 'access', _85 => _85[peak], 'optionalAccess', _86 => _86.pitch]), () => ( 0)))) {
|
|
3402
3643
|
peak = i;
|
|
3403
3644
|
}
|
|
3404
|
-
if ((_nullishCoalesce(_optionalChain([notes, 'access',
|
|
3645
|
+
if ((_nullishCoalesce(_optionalChain([notes, 'access', _87 => _87[i], 'optionalAccess', _88 => _88.pitch]), () => ( 0))) < (_nullishCoalesce(_optionalChain([notes, 'access', _89 => _89[trough], 'optionalAccess', _90 => _90.pitch]), () => ( 0)))) {
|
|
3405
3646
|
trough = i;
|
|
3406
3647
|
}
|
|
3407
3648
|
}
|
|
@@ -3414,7 +3655,7 @@ function melodicContour(notes) {
|
|
|
3414
3655
|
(step) => step > 0 ? "up" : step < 0 ? "down" : "same"
|
|
3415
3656
|
);
|
|
3416
3657
|
const { peak, trough } = extremes(line);
|
|
3417
|
-
const range = (_nullishCoalesce(_optionalChain([line, 'access',
|
|
3658
|
+
const range = (_nullishCoalesce(_optionalChain([line, 'access', _91 => _91[peak], 'optionalAccess', _92 => _92.pitch]), () => ( 0))) - (_nullishCoalesce(_optionalChain([line, 'access', _93 => _93[trough], 'optionalAccess', _94 => _94.pitch]), () => ( 0)));
|
|
3418
3659
|
const motion = intervals.reduce((sum, step) => sum + Math.abs(step), 0);
|
|
3419
3660
|
if (motion === 0) {
|
|
3420
3661
|
return {
|
|
@@ -3426,8 +3667,8 @@ function melodicContour(notes) {
|
|
|
3426
3667
|
rationale: line.length < 2 ? "Too short to have a direction, so the line is static" : "Every note at the same pitch, so the line is static"
|
|
3427
3668
|
};
|
|
3428
3669
|
}
|
|
3429
|
-
const first = _nullishCoalesce(_optionalChain([line, 'access',
|
|
3430
|
-
const last = _nullishCoalesce(_optionalChain([line, 'access',
|
|
3670
|
+
const first = _nullishCoalesce(_optionalChain([line, 'access', _95 => _95[0], 'optionalAccess', _96 => _96.pitch]), () => ( 0));
|
|
3671
|
+
const last = _nullishCoalesce(_optionalChain([line, 'access', _97 => _97[line.length - 1], 'optionalAccess', _98 => _98.pitch]), () => ( 0));
|
|
3431
3672
|
const net = last - first;
|
|
3432
3673
|
const directness = Math.abs(net) / motion;
|
|
3433
3674
|
const share = Math.round(directness * 100);
|
|
@@ -3439,10 +3680,10 @@ function melodicContour(notes) {
|
|
|
3439
3680
|
peakIndex: peak,
|
|
3440
3681
|
troughIndex: trough,
|
|
3441
3682
|
range,
|
|
3442
|
-
rationale:
|
|
3683
|
+
rationale: `The net ${net > 0 ? "rise" : "fall"} is ${share}% of the motion, so the line is ${shape}`
|
|
3443
3684
|
};
|
|
3444
3685
|
}
|
|
3445
|
-
const peakPitch = _nullishCoalesce(_optionalChain([line, 'access',
|
|
3686
|
+
const peakPitch = _nullishCoalesce(_optionalChain([line, 'access', _99 => _99[peak], 'optionalAccess', _100 => _100.pitch]), () => ( 0));
|
|
3446
3687
|
const archMotion = peakPitch - first + (peakPitch - last);
|
|
3447
3688
|
if (peak > 0 && peak < line.length - 1 && archMotion >= DIRECTIONAL_SHARE * motion) {
|
|
3448
3689
|
return {
|
|
@@ -3460,7 +3701,7 @@ function melodicContour(notes) {
|
|
|
3460
3701
|
peakIndex: peak,
|
|
3461
3702
|
troughIndex: trough,
|
|
3462
3703
|
range,
|
|
3463
|
-
rationale: `Changes direction without settling either way (${share}% of the motion
|
|
3704
|
+
rationale: `Changes direction without settling either way (the net movement is ${share}% of the motion), so the line is a wave`
|
|
3464
3705
|
};
|
|
3465
3706
|
}
|
|
3466
3707
|
|
|
@@ -3506,22 +3747,22 @@ function listBeats(occurrences) {
|
|
|
3506
3747
|
function motifFromGroup(group, notes) {
|
|
3507
3748
|
const first = _nullishCoalesce(group.starts[0], () => ( 0));
|
|
3508
3749
|
const prime = notes.slice(first, first + group.length).map((note) => ({ ...note }));
|
|
3509
|
-
const primePitch = _nullishCoalesce(_optionalChain([prime, 'access',
|
|
3750
|
+
const primePitch = _nullishCoalesce(_optionalChain([prime, 'access', _101 => _101[0], 'optionalAccess', _102 => _102.pitch]), () => ( 0));
|
|
3510
3751
|
const primeSpan = onsetSpan(prime);
|
|
3511
3752
|
const occurrences = group.starts.map((start) => {
|
|
3512
3753
|
const statement = notes.slice(start, start + group.length);
|
|
3513
3754
|
const span = onsetSpan(statement);
|
|
3514
3755
|
return {
|
|
3515
3756
|
noteIndex: start,
|
|
3516
|
-
startBeat: _nullishCoalesce(_optionalChain([statement, 'access',
|
|
3757
|
+
startBeat: _nullishCoalesce(_optionalChain([statement, 'access', _103 => _103[0], 'optionalAccess', _104 => _104.startBeat]), () => ( 0)),
|
|
3517
3758
|
endBeat: endBeatOf(statement),
|
|
3518
|
-
transpose: (_nullishCoalesce(_optionalChain([statement, 'access',
|
|
3519
|
-
timeRatio: primeSpan >
|
|
3759
|
+
transpose: (_nullishCoalesce(_optionalChain([statement, 'access', _105 => _105[0], 'optionalAccess', _106 => _106.pitch]), () => ( 0))) - primePitch,
|
|
3760
|
+
timeRatio: primeSpan > _chunkS3QELJUEcjs.BEAT_EPS ? span / primeSpan : 1
|
|
3520
3761
|
};
|
|
3521
3762
|
});
|
|
3522
3763
|
const shape = melodicContour(prime).shape;
|
|
3523
3764
|
const transposed = occurrences.some((occurrence) => occurrence.transpose !== 0);
|
|
3524
|
-
const stretched = occurrences.some((occurrence) => Math.abs(occurrence.timeRatio - 1) >
|
|
3765
|
+
const stretched = occurrences.some((occurrence) => Math.abs(occurrence.timeRatio - 1) > _chunkS3QELJUEcjs.BEAT_EPS);
|
|
3525
3766
|
const detail = [
|
|
3526
3767
|
transposed ? "at more than one pitch level" : "at the same pitch level",
|
|
3527
3768
|
stretched ? "and in more than one set of note values" : ""
|
|
@@ -3535,15 +3776,15 @@ function motifFromGroup(group, notes) {
|
|
|
3535
3776
|
};
|
|
3536
3777
|
}
|
|
3537
3778
|
function extractMotifs(notes, opts = {}) {
|
|
3538
|
-
const asked =
|
|
3539
|
-
const minNotes =
|
|
3540
|
-
const maxNotes =
|
|
3779
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
3780
|
+
const minNotes = _chunkS3QELJUEcjs.assertInteger.call(void 0, _nullishCoalesce(asked.minNotes, () => ( MIN_CELL_NOTES)), "motif minNotes", 2, 64);
|
|
3781
|
+
const maxNotes = _chunkS3QELJUEcjs.assertInteger.call(void 0, _nullishCoalesce(asked.maxNotes, () => ( MAX_CELL_NOTES)), "motif maxNotes", 2, 64);
|
|
3541
3782
|
if (maxNotes < minNotes) {
|
|
3542
|
-
throw new (0,
|
|
3783
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
3543
3784
|
`motif maxNotes must be at least minNotes ${minNotes}; received ${maxNotes}`
|
|
3544
3785
|
);
|
|
3545
3786
|
}
|
|
3546
|
-
const minOccurrences =
|
|
3787
|
+
const minOccurrences = _chunkS3QELJUEcjs.assertInteger.call(void 0,
|
|
3547
3788
|
_nullishCoalesce(asked.minOccurrences, () => ( MIN_OCCURRENCES)),
|
|
3548
3789
|
"motif minOccurrences",
|
|
3549
3790
|
2
|
|
@@ -3552,7 +3793,7 @@ function extractMotifs(notes, opts = {}) {
|
|
|
3552
3793
|
if (sounding.length < minNotes) {
|
|
3553
3794
|
return [];
|
|
3554
3795
|
}
|
|
3555
|
-
|
|
3796
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0,
|
|
3556
3797
|
sounding.length * (maxNotes - minNotes + 1),
|
|
3557
3798
|
"motif windows",
|
|
3558
3799
|
asked.budget
|
|
@@ -3599,7 +3840,7 @@ function extractMotifs(notes, opts = {}) {
|
|
|
3599
3840
|
}
|
|
3600
3841
|
}
|
|
3601
3842
|
}
|
|
3602
|
-
|
|
3843
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, comparisons, "motif subsumption comparisons", asked.budget);
|
|
3603
3844
|
if (!covered) {
|
|
3604
3845
|
kept.push(candidate);
|
|
3605
3846
|
let byStart = keptByLength.get(candidate.length);
|
|
@@ -3637,18 +3878,18 @@ function spellingOf(key) {
|
|
|
3637
3878
|
if (key === void 0) {
|
|
3638
3879
|
return "sharp";
|
|
3639
3880
|
}
|
|
3640
|
-
return
|
|
3881
|
+
return _chunkYDGMWH43cjs.keySignatureFifths.call(void 0, key.tonic, key.scale) < 0 ? "flat" : "sharp";
|
|
3641
3882
|
}
|
|
3642
3883
|
function intervalBetween(from, to, key) {
|
|
3643
|
-
const
|
|
3644
|
-
return
|
|
3884
|
+
const start = _chunkS3QELJUEcjs.midiToNote.call(void 0, from, spellingOf(key));
|
|
3885
|
+
return _chunkS3QELJUEcjs.spelledInterval.call(void 0, start, _chunkS3QELJUEcjs.transposeNote.call(void 0, start, to - from));
|
|
3645
3886
|
}
|
|
3646
3887
|
function intervalName(interval) {
|
|
3647
3888
|
return `${interval.descending && interval.semitones !== 0 ? "-" : ""}${interval.quality}${interval.number}`;
|
|
3648
3889
|
}
|
|
3649
3890
|
function ladderIndices(notes, key) {
|
|
3650
|
-
const root =
|
|
3651
|
-
const offsets =
|
|
3891
|
+
const root = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
3892
|
+
const offsets = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, key).map((pc) => _chunkS3QELJUEcjs.pitchClassOf.call(void 0, pc - root));
|
|
3652
3893
|
if (offsets.length === 0) {
|
|
3653
3894
|
return null;
|
|
3654
3895
|
}
|
|
@@ -3699,15 +3940,15 @@ function totalGap(gaps) {
|
|
|
3699
3940
|
}
|
|
3700
3941
|
function stretchRatio(modelGaps, answerGaps) {
|
|
3701
3942
|
const span = totalGap(modelGaps);
|
|
3702
|
-
return span >
|
|
3943
|
+
return span > _chunkS3QELJUEcjs.BEAT_EPS ? totalGap(answerGaps) / span : 1;
|
|
3703
3944
|
}
|
|
3704
3945
|
function stretchPhrase(ratio2) {
|
|
3705
3946
|
return `note values ${roundTo(ratio2, 3)}x the model's`;
|
|
3706
3947
|
}
|
|
3707
3948
|
function relateMotifs(a, b, keyLike) {
|
|
3708
|
-
const key = keyLike === void 0 ? void 0 :
|
|
3709
|
-
const model =
|
|
3710
|
-
const answer =
|
|
3949
|
+
const key = keyLike === void 0 ? void 0 : _chunkYDGMWH43cjs.resolveKey.call(void 0, keyLike);
|
|
3950
|
+
const model = _chunkS3QELJUEcjs.assertArray.call(void 0, _chunkS3QELJUEcjs.assertRecord.call(void 0, a, "a").notes, "a.notes");
|
|
3951
|
+
const answer = _chunkS3QELJUEcjs.assertArray.call(void 0, _chunkS3QELJUEcjs.assertRecord.call(void 0, b, "b").notes, "b.notes");
|
|
3711
3952
|
if (model.length === 0 || model.length !== answer.length) {
|
|
3712
3953
|
return null;
|
|
3713
3954
|
}
|
|
@@ -3722,12 +3963,12 @@ function relateMotifs(a, b, keyLike) {
|
|
|
3722
3963
|
}
|
|
3723
3964
|
const forward = sameNumbers(modelProfile, answerProfile);
|
|
3724
3965
|
const backward = retroProfile !== null && sameNumbers(retroProfile, answerProfile);
|
|
3725
|
-
const semitones = (_nullishCoalesce(_optionalChain([answer, 'access',
|
|
3726
|
-
const interval = intervalBetween(_nullishCoalesce(_optionalChain([model, 'access',
|
|
3727
|
-
const gap = (_nullishCoalesce(_optionalChain([answer, 'access',
|
|
3966
|
+
const semitones = (_nullishCoalesce(_optionalChain([answer, 'access', _107 => _107[0], 'optionalAccess', _108 => _108.pitch]), () => ( 0))) - (_nullishCoalesce(_optionalChain([model, 'access', _109 => _109[0], 'optionalAccess', _110 => _110.pitch]), () => ( 0)));
|
|
3967
|
+
const interval = intervalBetween(_nullishCoalesce(_optionalChain([model, 'access', _111 => _111[0], 'optionalAccess', _112 => _112.pitch]), () => ( 0)), _nullishCoalesce(_optionalChain([answer, 'access', _113 => _113[0], 'optionalAccess', _114 => _114.pitch]), () => ( 0)), key);
|
|
3968
|
+
const gap = (_nullishCoalesce(_optionalChain([answer, 'access', _115 => _115[0], 'optionalAccess', _116 => _116.startBeat]), () => ( 0))) - endBeatOf(model);
|
|
3728
3969
|
const sequence = gap >= -HUMANIZE_ADJACENCY && gap <= HUMANIZE_ADJACENCY;
|
|
3729
3970
|
const timeRatio = stretchRatio(modelGaps, answerGaps);
|
|
3730
|
-
const stretched = Math.abs(timeRatio - 1) >
|
|
3971
|
+
const stretched = Math.abs(timeRatio - 1) > _chunkS3QELJUEcjs.BEAT_EPS;
|
|
3731
3972
|
const shapes = pitchShapes(intervalsOf(model), intervalsOf(answer));
|
|
3732
3973
|
const base = { sequence, semitones, interval, timeRatio };
|
|
3733
3974
|
const backwardBase = { ...base, timeRatio: stretchRatio(retroGaps, answerGaps) };
|
|
@@ -3771,11 +4012,12 @@ function relateMotifs(a, b, keyLike) {
|
|
|
3771
4012
|
}
|
|
3772
4013
|
}
|
|
3773
4014
|
}
|
|
3774
|
-
|
|
4015
|
+
const literalRetrograde = backward && shapes.includes("retrograde") && _optionalChain([answer, 'access', _117 => _117[0], 'optionalAccess', _118 => _118.pitch]) === _optionalChain([model, 'access', _119 => _119[model.length - 1], 'optionalAccess', _120 => _120.pitch]);
|
|
4016
|
+
if (forward && shapes.includes("inversion") && !(literalRetrograde && semitones !== 0)) {
|
|
3775
4017
|
return {
|
|
3776
4018
|
...base,
|
|
3777
4019
|
kind: "inversion",
|
|
3778
|
-
rationale:
|
|
4020
|
+
rationale: `Inversion: every interval turned upside down${semitones === 0 ? " about the first note" : ""}` + (stretched ? `, in ${stretchPhrase(timeRatio)}` : "")
|
|
3779
4021
|
};
|
|
3780
4022
|
}
|
|
3781
4023
|
if (backward && shapes.includes("retrograde")) {
|
|
@@ -3829,8 +4071,8 @@ function intervalCost(x, y) {
|
|
|
3829
4071
|
return Math.min(1, Math.abs(x - y) / INTERVAL_TOLERANCE);
|
|
3830
4072
|
}
|
|
3831
4073
|
function gapCost(x, y) {
|
|
3832
|
-
if (!(x >
|
|
3833
|
-
return Math.abs(x - y) >
|
|
4074
|
+
if (!(x > _chunkS3QELJUEcjs.BEAT_EPS) || !(y > _chunkS3QELJUEcjs.BEAT_EPS)) {
|
|
4075
|
+
return Math.abs(x - y) > _chunkS3QELJUEcjs.BEAT_EPS ? 1 : 0;
|
|
3834
4076
|
}
|
|
3835
4077
|
return Math.min(1, Math.abs(Math.log2(x / y)));
|
|
3836
4078
|
}
|
|
@@ -3839,6 +4081,7 @@ function compareMelodies(a, b) {
|
|
|
3839
4081
|
const right = orderedNotes(phraseNotes(b), "melody b");
|
|
3840
4082
|
const leftIntervals = intervalsOf(left);
|
|
3841
4083
|
const rightIntervals = intervalsOf(right);
|
|
4084
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, leftIntervals.length * rightIntervals.length, "melody alignment");
|
|
3842
4085
|
const pitchSimilarity = distanceToSimilarity(
|
|
3843
4086
|
gradedEditDistance(leftIntervals, rightIntervals, intervalCost),
|
|
3844
4087
|
leftIntervals.length,
|
|
@@ -3884,28 +4127,28 @@ function betterParent(candidate, current) {
|
|
|
3884
4127
|
return candidate.index < current.index;
|
|
3885
4128
|
}
|
|
3886
4129
|
function motifGraph(line, motifs, opts = {}) {
|
|
3887
|
-
const asked =
|
|
4130
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
3888
4131
|
const variationThreshold = _nullishCoalesce(asked.variationThreshold, () => ( DEFAULT_VARIATION_THRESHOLD));
|
|
3889
|
-
|
|
4132
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, variationThreshold, 0, 1, "motif graph variationThreshold");
|
|
3890
4133
|
const ordered = orderedNotes(line, "line", asked.budget);
|
|
3891
|
-
const motifList =
|
|
4134
|
+
const motifList = _chunkS3QELJUEcjs.assertArray.call(void 0, motifs, "motifs");
|
|
3892
4135
|
const infos = [];
|
|
3893
4136
|
for (let mi = 0; mi < motifList.length; mi += 1) {
|
|
3894
|
-
const motif =
|
|
3895
|
-
const notes =
|
|
3896
|
-
const occurrences =
|
|
4137
|
+
const motif = _chunkS3QELJUEcjs.assertRecord.call(void 0, motifList[mi], `motifs[${mi}]`);
|
|
4138
|
+
const notes = _chunkS3QELJUEcjs.assertArray.call(void 0, motif.notes, `motifs[${mi}].notes`);
|
|
4139
|
+
const occurrences = _chunkS3QELJUEcjs.assertArray.call(void 0,
|
|
3897
4140
|
motif.occurrences,
|
|
3898
4141
|
`motifs[${mi}].occurrences`
|
|
3899
4142
|
);
|
|
3900
4143
|
for (let oi = 0; oi < occurrences.length; oi += 1) {
|
|
3901
|
-
const occurrence =
|
|
4144
|
+
const occurrence = _chunkS3QELJUEcjs.assertRecord.call(void 0,
|
|
3902
4145
|
occurrences[oi],
|
|
3903
4146
|
`motifs[${mi}].occurrences[${oi}]`
|
|
3904
4147
|
);
|
|
3905
4148
|
const { noteIndex } = occurrence;
|
|
3906
|
-
const onLine = Number.isInteger(noteIndex) && noteIndex >= 0 && noteIndex + notes.length <= ordered.length && Math.abs((_nullishCoalesce(_optionalChain([ordered, 'access',
|
|
4149
|
+
const onLine = Number.isInteger(noteIndex) && noteIndex >= 0 && noteIndex + notes.length <= ordered.length && Math.abs((_nullishCoalesce(_optionalChain([ordered, 'access', _121 => _121[noteIndex], 'optionalAccess', _122 => _122.startBeat]), () => ( Number.NaN))) - occurrence.startBeat) <= _chunkS3QELJUEcjs.BEAT_EPS;
|
|
3907
4150
|
if (!onLine) {
|
|
3908
|
-
throw new (0,
|
|
4151
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
3909
4152
|
`motif occurrence motifs[${mi}].occurrences[${oi}] does not lie on the line`
|
|
3910
4153
|
);
|
|
3911
4154
|
}
|
|
@@ -3922,7 +4165,7 @@ function motifGraph(line, motifs, opts = {}) {
|
|
|
3922
4165
|
}
|
|
3923
4166
|
infos.sort((a, b) => a.node.startBeat - b.node.startBeat || a.node.motif - b.node.motif);
|
|
3924
4167
|
const nodeCount = infos.length;
|
|
3925
|
-
|
|
4168
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, nodeCount * nodeCount, "motif graph comparisons", asked.budget);
|
|
3926
4169
|
const edges = [];
|
|
3927
4170
|
for (let to = 1; to < nodeCount; to += 1) {
|
|
3928
4171
|
const toInfo = infos[to];
|
|
@@ -3953,16 +4196,22 @@ function motifGraph(line, motifs, opts = {}) {
|
|
|
3953
4196
|
|
|
3954
4197
|
// src/analyze/reduction/index.ts
|
|
3955
4198
|
var REDUCTION_LEVELS = Object.freeze(["structural", "passing", "neighbor"]);
|
|
3956
|
-
var
|
|
4199
|
+
var TONIC_ARRIVING_CADENCES = [
|
|
4200
|
+
"authentic",
|
|
4201
|
+
"plagal",
|
|
4202
|
+
"modal",
|
|
4203
|
+
"deceptive"
|
|
4204
|
+
];
|
|
4205
|
+
var TONIC_ARRIVING = new Set(TONIC_ARRIVING_CADENCES);
|
|
3957
4206
|
function signedStep(fromPc, toPc) {
|
|
3958
|
-
return (
|
|
4207
|
+
return (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, toPc) - _chunkS3QELJUEcjs.pitchClassOf.call(void 0, fromPc) + 18) % 12 - 6;
|
|
3959
4208
|
}
|
|
3960
4209
|
function isStep2(distance) {
|
|
3961
4210
|
const size = Math.abs(distance);
|
|
3962
4211
|
return size === 1 || size === 2;
|
|
3963
4212
|
}
|
|
3964
4213
|
function touches(before, after) {
|
|
3965
|
-
return Math.abs(after.startBeat - before.endBeat) <=
|
|
4214
|
+
return Math.abs(after.startBeat - before.endBeat) <= _chunkS3QELJUEcjs.BEAT_EPS;
|
|
3966
4215
|
}
|
|
3967
4216
|
function salienceFloors(durations) {
|
|
3968
4217
|
const order = durations.map((_, index) => index).sort((a, b) => {
|
|
@@ -3989,7 +4238,7 @@ function salienceFloors(durations) {
|
|
|
3989
4238
|
return floors;
|
|
3990
4239
|
}
|
|
3991
4240
|
function isTonicChord(chord, key) {
|
|
3992
|
-
return
|
|
4241
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc) === 0 && !isAppliedDominant(chord, key);
|
|
3993
4242
|
}
|
|
3994
4243
|
function functionalReason(segment, before, after, keyAt) {
|
|
3995
4244
|
const key = keyAt(segment.startBeat);
|
|
@@ -3999,7 +4248,7 @@ function functionalReason(segment, before, after, keyAt) {
|
|
|
3999
4248
|
if (isTonicChord(segment.chord, key)) {
|
|
4000
4249
|
return { kind: "tonic" };
|
|
4001
4250
|
}
|
|
4002
|
-
if (
|
|
4251
|
+
if (_chunkYDGMWH43cjs.isDominantChordOf.call(void 0, segment.chord, key)) {
|
|
4003
4252
|
return { kind: "dominant" };
|
|
4004
4253
|
}
|
|
4005
4254
|
if (before !== void 0) {
|
|
@@ -4028,7 +4277,7 @@ function figureReason(segment, before, after) {
|
|
|
4028
4277
|
if (incoming > 0 === outgoing > 0) {
|
|
4029
4278
|
return { kind: "passing" };
|
|
4030
4279
|
}
|
|
4031
|
-
return
|
|
4280
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, before.chord.rootPc) === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, after.chord.rootPc) ? { kind: "neighbor" } : null;
|
|
4032
4281
|
}
|
|
4033
4282
|
function describe2(reason) {
|
|
4034
4283
|
switch (reason.kind) {
|
|
@@ -4069,9 +4318,9 @@ function levelOf(reason) {
|
|
|
4069
4318
|
}
|
|
4070
4319
|
function reduceProgression(timeline, key, opts = {}) {
|
|
4071
4320
|
assertChordTimeline(timeline);
|
|
4072
|
-
const asked =
|
|
4321
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
4073
4322
|
const keyAt = keyScaleAt(key);
|
|
4074
|
-
const basis =
|
|
4323
|
+
const basis = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(asked.basis, () => ( "function")), REDUCTION_BASES, "reduction basis");
|
|
4075
4324
|
const reading = BASIS_READINGS[basis];
|
|
4076
4325
|
const segments = timeline.segments;
|
|
4077
4326
|
const floors = basis === "duration" ? salienceFloors(segments.map((segment) => segment.endBeat - segment.startBeat)) : [];
|
|
@@ -4104,27 +4353,38 @@ function reduceProgression(timeline, key, opts = {}) {
|
|
|
4104
4353
|
return result;
|
|
4105
4354
|
}
|
|
4106
4355
|
|
|
4356
|
+
// src/analyze/reference/types.ts
|
|
4357
|
+
var REFERENCE_PROFILE_VERSION = 1;
|
|
4358
|
+
var PHRASE_OUTLINE_POINTS = 8;
|
|
4359
|
+
var MIDI_MAX = 127;
|
|
4360
|
+
|
|
4107
4361
|
// src/analyze/rhythm/internal.ts
|
|
4108
4362
|
function isMultipleOf(value, unit) {
|
|
4109
4363
|
if (unit <= 0) {
|
|
4110
4364
|
return false;
|
|
4111
4365
|
}
|
|
4112
4366
|
const ratio2 = value / unit;
|
|
4113
|
-
return Math.abs(ratio2 - Math.round(ratio2)) <
|
|
4367
|
+
return Math.abs(ratio2 - Math.round(ratio2)) < _chunkS3QELJUEcjs.BEAT_EPS;
|
|
4114
4368
|
}
|
|
4115
4369
|
function rhythmLevel(beatInQuarters, meters) {
|
|
4116
|
-
const ts =
|
|
4117
|
-
const offset = beatInQuarters -
|
|
4118
|
-
const pulse =
|
|
4370
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, beatInQuarters, meters);
|
|
4371
|
+
const offset = beatInQuarters - _chunkS3QELJUEcjs.barStartBeat.call(void 0, beatInQuarters, meters);
|
|
4372
|
+
const pulse = _chunkS3QELJUEcjs.pulseBeats.call(void 0, ts);
|
|
4119
4373
|
if (isMultipleOf(offset, pulse)) {
|
|
4120
|
-
return
|
|
4374
|
+
return _chunkS3QELJUEcjs.metricWeight.call(void 0, beatInQuarters, meters) + 2;
|
|
4121
4375
|
}
|
|
4122
|
-
const subUnit = pulse / (
|
|
4376
|
+
const subUnit = pulse / (_chunkS3QELJUEcjs.isCompound.call(void 0, ts) ? 3 : 2);
|
|
4123
4377
|
return isMultipleOf(offset, subUnit) ? 1 : 0;
|
|
4124
4378
|
}
|
|
4379
|
+
var IOI_MIN_EXPONENT = -4;
|
|
4380
|
+
var IOI_MAX_EXPONENT = 4;
|
|
4381
|
+
var IOI_EXPONENT_STEP = 0.5;
|
|
4125
4382
|
function ioiBinIndex(ioi) {
|
|
4126
|
-
const exponent = Math.min(
|
|
4127
|
-
|
|
4383
|
+
const exponent = Math.min(
|
|
4384
|
+
IOI_MAX_EXPONENT,
|
|
4385
|
+
Math.max(IOI_MIN_EXPONENT, Math.round(2 * Math.log2(ioi)) / 2)
|
|
4386
|
+
);
|
|
4387
|
+
return Math.round((exponent - IOI_MIN_EXPONENT) / IOI_EXPONENT_STEP);
|
|
4128
4388
|
}
|
|
4129
4389
|
|
|
4130
4390
|
// src/analyze/rhythm/index.ts
|
|
@@ -4134,6 +4394,8 @@ var RHYTHM_OFF_GRID_TOLERANCE = 1 / 32;
|
|
|
4134
4394
|
var RHYTHM_IOI_BINS = Object.freeze(
|
|
4135
4395
|
Array.from({ length: 17 }, (_, i) => 2 ** (-4 + i * 0.5))
|
|
4136
4396
|
);
|
|
4397
|
+
var BUDGET_SLOTS_PER_BAR = 48;
|
|
4398
|
+
var RHYTHM_LEVEL_COUNT = 6;
|
|
4137
4399
|
function emptyAnalysis() {
|
|
4138
4400
|
return {
|
|
4139
4401
|
startBeat: 0,
|
|
@@ -4142,7 +4404,7 @@ function emptyAnalysis() {
|
|
|
4142
4404
|
onsets: 0,
|
|
4143
4405
|
onsetDensity: 0,
|
|
4144
4406
|
barOnsets: [],
|
|
4145
|
-
onsetLevels: new Array(
|
|
4407
|
+
onsetLevels: new Array(RHYTHM_LEVEL_COUNT).fill(0),
|
|
4146
4408
|
barPositions: [],
|
|
4147
4409
|
interOnsetShares: new Array(RHYTHM_IOI_BINS.length).fill(0),
|
|
4148
4410
|
restRatio: 0,
|
|
@@ -4166,8 +4428,8 @@ function foldOnsets(sounding) {
|
|
|
4166
4428
|
return onsets;
|
|
4167
4429
|
}
|
|
4168
4430
|
function snapOnset(onset, meters) {
|
|
4169
|
-
const ts =
|
|
4170
|
-
const barStart =
|
|
4431
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, onset.beat, meters);
|
|
4432
|
+
const barStart = _chunkS3QELJUEcjs.barStartBeat.call(void 0, onset.beat, meters);
|
|
4171
4433
|
const offset = onset.beat - barStart;
|
|
4172
4434
|
const slot = Math.round(offset / SLOT_WIDTH);
|
|
4173
4435
|
const snapped = barStart + slot * SLOT_WIDTH;
|
|
@@ -4177,13 +4439,47 @@ function snapOnset(onset, meters) {
|
|
|
4177
4439
|
function tsKey(ts) {
|
|
4178
4440
|
return ts.grouping === void 0 ? `${ts.numerator}/${ts.denominator}` : `${ts.numerator}/${ts.denominator}:${ts.grouping.join("+")}`;
|
|
4179
4441
|
}
|
|
4180
|
-
function
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
const
|
|
4442
|
+
function pulseKey(bar, index) {
|
|
4443
|
+
return `${bar}/${index}`;
|
|
4444
|
+
}
|
|
4445
|
+
function otherDivisionPulses(snapped, meters) {
|
|
4446
|
+
const pulses = /* @__PURE__ */ new Set();
|
|
4447
|
+
for (const onset of snapped) {
|
|
4448
|
+
const pulse = _chunkS3QELJUEcjs.pulseBeats.call(void 0, onset.ts);
|
|
4449
|
+
const offset = onset.snapped - onset.barStart;
|
|
4450
|
+
const index = Math.floor(offset / pulse + _chunkS3QELJUEcjs.BEAT_EPS);
|
|
4451
|
+
const within = offset - index * pulse;
|
|
4452
|
+
const [used, other] = _chunkS3QELJUEcjs.isCompound.call(void 0, onset.ts) ? [3, 2] : [2, 3];
|
|
4453
|
+
if (isMultipleOf(within, pulse / other) && !isMultipleOf(within, pulse / used)) {
|
|
4454
|
+
pulses.add(pulseKey(_chunkS3QELJUEcjs.barIndexAt.call(void 0, onset.beat, meters), index));
|
|
4455
|
+
}
|
|
4456
|
+
}
|
|
4457
|
+
return pulses;
|
|
4458
|
+
}
|
|
4459
|
+
function barGridPoints(bar, meters, otherPulses) {
|
|
4460
|
+
const barStart = _chunkS3QELJUEcjs.barPositionToBeat.call(void 0, { bar, beat: 0 }, meters);
|
|
4461
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, barStart, meters);
|
|
4462
|
+
const barLength = _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, barStart, meters);
|
|
4463
|
+
const pulse = _chunkS3QELJUEcjs.pulseBeats.call(void 0, ts);
|
|
4464
|
+
const [used, other] = _chunkS3QELJUEcjs.isCompound.call(void 0, ts) ? [3, 2] : [2, 3];
|
|
4465
|
+
const subUnit = pulse / used;
|
|
4185
4466
|
const steps = Math.max(1, Math.round(barLength / subUnit));
|
|
4186
|
-
|
|
4467
|
+
const points = [];
|
|
4468
|
+
for (let k = 0; k < steps; k += 1) {
|
|
4469
|
+
const index = Math.floor(k * subUnit / pulse + _chunkS3QELJUEcjs.BEAT_EPS);
|
|
4470
|
+
if (k % used === 0 || !otherPulses.has(pulseKey(bar, index))) {
|
|
4471
|
+
const beat = barStart + k * subUnit;
|
|
4472
|
+
points.push({ beat, level: rhythmLevel(beat, meters) });
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
for (let index = 0; index * pulse < steps * subUnit - _chunkS3QELJUEcjs.BEAT_EPS; index += 1) {
|
|
4476
|
+
if (otherPulses.has(pulseKey(bar, index))) {
|
|
4477
|
+
for (let m = 1; m < other; m += 1) {
|
|
4478
|
+
points.push({ beat: barStart + index * pulse + m * pulse / other, level: 1 });
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
}
|
|
4482
|
+
return points.sort((a, b) => a.beat - b.beat);
|
|
4187
4483
|
}
|
|
4188
4484
|
function restRatioOf(sounding, windowStart, windowEnd) {
|
|
4189
4485
|
const span = windowEnd - windowStart;
|
|
@@ -4217,13 +4513,14 @@ function syncopationOf(snapped, startBeat, endBeat, meters) {
|
|
|
4217
4513
|
if (snapped.length === 0) {
|
|
4218
4514
|
return 0;
|
|
4219
4515
|
}
|
|
4220
|
-
const firstBar =
|
|
4221
|
-
const lastBar =
|
|
4516
|
+
const firstBar = _chunkS3QELJUEcjs.barIndexAt.call(void 0, startBeat, meters);
|
|
4517
|
+
const lastBar = _chunkS3QELJUEcjs.barIndexAt.call(void 0, endBeat, meters);
|
|
4518
|
+
const otherPulses = otherDivisionPulses(snapped, meters);
|
|
4222
4519
|
const points = [];
|
|
4223
4520
|
for (let bar = firstBar; bar <= lastBar; bar += 1) {
|
|
4224
|
-
for (const
|
|
4225
|
-
if (beat > startBeat +
|
|
4226
|
-
points.push(
|
|
4521
|
+
for (const point of barGridPoints(bar, meters, otherPulses)) {
|
|
4522
|
+
if (point.beat > startBeat + _chunkS3QELJUEcjs.BEAT_EPS && point.beat <= endBeat + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
4523
|
+
points.push(point);
|
|
4227
4524
|
}
|
|
4228
4525
|
}
|
|
4229
4526
|
}
|
|
@@ -4240,51 +4537,59 @@ function syncopationOf(snapped, startBeat, endBeat, meters) {
|
|
|
4240
4537
|
}
|
|
4241
4538
|
const next = snapped[i + 1];
|
|
4242
4539
|
const windowEnd = next !== void 0 ? next.snapped : onset.end;
|
|
4243
|
-
while (ptr < points.length && (_nullishCoalesce(_optionalChain([points, 'access',
|
|
4540
|
+
while (ptr < points.length && (_nullishCoalesce(_optionalChain([points, 'access', _123 => _123[ptr], 'optionalAccess', _124 => _124.beat]), () => ( Number.POSITIVE_INFINITY))) <= onset.snapped + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
4244
4541
|
ptr += 1;
|
|
4245
4542
|
}
|
|
4543
|
+
const here = ptr > 0 ? points[ptr - 1] : void 0;
|
|
4544
|
+
const onsetLevel = here !== void 0 && Math.abs(here.beat - onset.snapped) < _chunkS3QELJUEcjs.BEAT_EPS ? Math.max(onset.level, here.level) : onset.level;
|
|
4246
4545
|
let scan = ptr;
|
|
4247
4546
|
let maxLevel = 0;
|
|
4248
|
-
while (scan < points.length && (_nullishCoalesce(_optionalChain([points, 'access',
|
|
4249
|
-
maxLevel = Math.max(maxLevel, _nullishCoalesce(_optionalChain([points, 'access',
|
|
4547
|
+
while (scan < points.length && (_nullishCoalesce(_optionalChain([points, 'access', _125 => _125[scan], 'optionalAccess', _126 => _126.beat]), () => ( Number.POSITIVE_INFINITY))) < windowEnd - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
4548
|
+
maxLevel = Math.max(maxLevel, _nullishCoalesce(_optionalChain([points, 'access', _127 => _127[scan], 'optionalAccess', _128 => _128.level]), () => ( 0)));
|
|
4250
4549
|
scan += 1;
|
|
4251
4550
|
}
|
|
4252
|
-
if (maxLevel >
|
|
4253
|
-
numerator += maxLevel -
|
|
4551
|
+
if (maxLevel > onsetLevel) {
|
|
4552
|
+
numerator += maxLevel - onsetLevel;
|
|
4254
4553
|
}
|
|
4255
4554
|
ptr = scan;
|
|
4256
4555
|
}
|
|
4257
4556
|
return numerator / normalizer;
|
|
4258
4557
|
}
|
|
4259
4558
|
function analyzeRhythm(notes, opts = {}) {
|
|
4260
|
-
|
|
4261
|
-
|
|
4559
|
+
return rhythmOver(notes, opts, void 0);
|
|
4560
|
+
}
|
|
4561
|
+
function rhythmOver(notes, opts, windowStart) {
|
|
4562
|
+
const meters = _chunkS3QELJUEcjs.resolveMeters.call(void 0, opts, "rhythm meters");
|
|
4563
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, notes, "rhythm notes", { allowNonPositiveDuration: true, budget: opts.budget });
|
|
4262
4564
|
const sounding = notes.filter((note) => note.durationBeat > 0);
|
|
4565
|
+
const startBeat = _nullishCoalesce(windowStart, () => ( barGridStart(firstSoundingBeat(sounding), meters)));
|
|
4566
|
+
const endBeat = resolveSpanEnd(
|
|
4567
|
+
opts.totalBeats,
|
|
4568
|
+
startBeat,
|
|
4569
|
+
latestSoundingEnd(sounding),
|
|
4570
|
+
"rhythm totalBeats"
|
|
4571
|
+
);
|
|
4263
4572
|
if (sounding.length === 0) {
|
|
4264
4573
|
return emptyAnalysis();
|
|
4265
4574
|
}
|
|
4266
|
-
const firstOnset = sounding.reduce(
|
|
4267
|
-
(min, n) => Math.min(min, n.startBeat),
|
|
4268
|
-
Number.POSITIVE_INFINITY
|
|
4269
|
-
);
|
|
4270
|
-
const startBeat = barGridStart(firstOnset, meters);
|
|
4271
|
-
const lastEnd = sounding.reduce((end, n) => Math.max(end, n.startBeat + n.durationBeat), 0);
|
|
4272
|
-
const endBeat = Math.max(startBeat, _nullishCoalesce(opts.totalBeats, () => ( lastEnd)));
|
|
4273
|
-
_chunkS5BKZZGMcjs.assertRange.call(void 0, endBeat, 0, Number.MAX_SAFE_INTEGER, "rhythm totalBeats");
|
|
4274
4575
|
const bars = barSpanOf(startBeat, endBeat, meters);
|
|
4275
|
-
|
|
4576
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0,
|
|
4577
|
+
Math.ceil(bars) * BUDGET_SLOTS_PER_BAR,
|
|
4578
|
+
"rhythm analysis slots",
|
|
4579
|
+
opts.budget
|
|
4580
|
+
);
|
|
4276
4581
|
const onsets = foldOnsets(sounding);
|
|
4277
4582
|
const snapped = onsets.map((onset) => snapOnset(onset, meters));
|
|
4278
4583
|
const onsetDensity = bars > 0 ? onsets.length / bars : 0;
|
|
4279
|
-
const firstBar =
|
|
4584
|
+
const firstBar = _chunkS3QELJUEcjs.barIndexAt.call(void 0, startBeat, meters);
|
|
4280
4585
|
const barOnsets = new Array(lastBarOf(meters, startBeat, endBeat) - firstBar + 1).fill(0);
|
|
4281
4586
|
for (const onset of onsets) {
|
|
4282
|
-
const index =
|
|
4587
|
+
const index = _chunkS3QELJUEcjs.barIndexAt.call(void 0, onset.beat, meters) - firstBar;
|
|
4283
4588
|
if (index >= 0 && index < barOnsets.length) {
|
|
4284
4589
|
barOnsets[index] = (_nullishCoalesce(barOnsets[index], () => ( 0))) + 1;
|
|
4285
4590
|
}
|
|
4286
4591
|
}
|
|
4287
|
-
const onsetLevels = new Array(
|
|
4592
|
+
const onsetLevels = new Array(RHYTHM_LEVEL_COUNT).fill(0);
|
|
4288
4593
|
let offGridCount = 0;
|
|
4289
4594
|
for (const onset of snapped) {
|
|
4290
4595
|
onsetLevels[onset.level] = (_nullishCoalesce(onsetLevels[onset.level], () => ( 0))) + 1;
|
|
@@ -4303,7 +4608,7 @@ function analyzeRhythm(notes, opts = {}) {
|
|
|
4303
4608
|
if (index === void 0) {
|
|
4304
4609
|
index = profiles.length;
|
|
4305
4610
|
profileIndex.set(key, index);
|
|
4306
|
-
const slotsPerBar = Math.ceil(
|
|
4611
|
+
const slotsPerBar = Math.ceil(_chunkS3QELJUEcjs.beatsPerBar.call(void 0, onset.ts) * RHYTHM_SLOTS_PER_BEAT);
|
|
4307
4612
|
profiles.push({
|
|
4308
4613
|
ts: onset.ts,
|
|
4309
4614
|
slotsPerBar,
|
|
@@ -4357,40 +4662,37 @@ function analyzeRhythm(notes, opts = {}) {
|
|
|
4357
4662
|
};
|
|
4358
4663
|
}
|
|
4359
4664
|
|
|
4360
|
-
// src/analyze/reference/types.ts
|
|
4361
|
-
var REFERENCE_PROFILE_VERSION = 1;
|
|
4362
|
-
|
|
4363
4665
|
// src/analyze/reference/validate.ts
|
|
4364
4666
|
var MASS_TOLERANCE = 1e-9;
|
|
4365
4667
|
function assertString(value, name) {
|
|
4366
4668
|
if (typeof value !== "string") {
|
|
4367
|
-
throw new (0,
|
|
4669
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must be a string; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, value)}`);
|
|
4368
4670
|
}
|
|
4369
4671
|
return value;
|
|
4370
4672
|
}
|
|
4371
4673
|
function assertSpanOrder(startBeat, endBeat, name) {
|
|
4372
4674
|
if (endBeat < startBeat) {
|
|
4373
|
-
throw new (0,
|
|
4675
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4374
4676
|
`${name}.endBeat must be at least ${name}.startBeat; received ${endBeat} < ${startBeat}`
|
|
4375
4677
|
);
|
|
4376
4678
|
}
|
|
4377
4679
|
}
|
|
4378
4680
|
function assertNullable(value, name, validate) {
|
|
4379
4681
|
if (value === void 0) {
|
|
4380
|
-
throw new (0,
|
|
4682
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must be present; received undefined`);
|
|
4381
4683
|
}
|
|
4382
4684
|
return value === null ? null : validate(value, name);
|
|
4383
4685
|
}
|
|
4384
4686
|
function assertMassDistribution(value, length, name, allowAllZero) {
|
|
4385
|
-
const shares =
|
|
4687
|
+
const shares = _chunkS3QELJUEcjs.assertArray.call(void 0, value, name);
|
|
4386
4688
|
if (shares.length !== length) {
|
|
4387
|
-
throw new (0,
|
|
4689
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must have length ${length}; received ${shares.length}`);
|
|
4388
4690
|
}
|
|
4389
4691
|
let sum = 0;
|
|
4390
4692
|
for (let index = 0; index < shares.length; index += 1) {
|
|
4391
|
-
const share =
|
|
4693
|
+
const share = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, shares[index], `${name}[${index}]`);
|
|
4392
4694
|
if (share < 0) {
|
|
4393
|
-
throw new (0,
|
|
4695
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}[${index}] must be at least 0; received ${share}`);
|
|
4394
4696
|
}
|
|
4395
4697
|
sum += share;
|
|
4396
4698
|
}
|
|
@@ -4398,37 +4700,37 @@ function assertMassDistribution(value, length, name, allowAllZero) {
|
|
|
4398
4700
|
return shares;
|
|
4399
4701
|
}
|
|
4400
4702
|
if (Math.abs(sum - 1) > MASS_TOLERANCE) {
|
|
4401
|
-
throw new (0,
|
|
4703
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must sum to 1; received ${sum}`);
|
|
4402
4704
|
}
|
|
4403
4705
|
return shares;
|
|
4404
4706
|
}
|
|
4405
4707
|
function assertBarPositionProfile(value, name) {
|
|
4406
|
-
const read =
|
|
4407
|
-
|
|
4408
|
-
const slotsPerBar =
|
|
4409
|
-
const onsets =
|
|
4708
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4709
|
+
_chunkS3QELJUEcjs.assertTimeSignature.call(void 0, read.ts, `${name}.ts`);
|
|
4710
|
+
const slotsPerBar = _chunkS3QELJUEcjs.assertPositiveInt.call(void 0, read.slotsPerBar, `${name}.slotsPerBar`);
|
|
4711
|
+
const onsets = _chunkS3QELJUEcjs.assertInteger.call(void 0, read.onsets, `${name}.onsets`, 0);
|
|
4410
4712
|
assertMassDistribution(read.shares, slotsPerBar, `${name}.shares`, onsets === 0);
|
|
4411
4713
|
return read;
|
|
4412
4714
|
}
|
|
4413
4715
|
function assertRhythmAnalysis(value, name) {
|
|
4414
|
-
const read =
|
|
4415
|
-
const startBeat =
|
|
4416
|
-
const endBeat =
|
|
4716
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4717
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
4718
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
4417
4719
|
assertSpanOrder(startBeat, endBeat, name);
|
|
4418
|
-
|
|
4419
|
-
const onsets =
|
|
4420
|
-
|
|
4421
|
-
const barOnsets =
|
|
4720
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.bars, 0, Number.MAX_SAFE_INTEGER, `${name}.bars`);
|
|
4721
|
+
const onsets = _chunkS3QELJUEcjs.assertInteger.call(void 0, read.onsets, `${name}.onsets`, 0);
|
|
4722
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.onsetDensity, 0, Number.MAX_SAFE_INTEGER, `${name}.onsetDensity`);
|
|
4723
|
+
const barOnsets = _chunkS3QELJUEcjs.assertArray.call(void 0, read.barOnsets, `${name}.barOnsets`);
|
|
4422
4724
|
for (let index = 0; index < barOnsets.length; index += 1) {
|
|
4423
|
-
|
|
4725
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0,
|
|
4424
4726
|
barOnsets[index],
|
|
4425
4727
|
0,
|
|
4426
4728
|
Number.MAX_SAFE_INTEGER,
|
|
4427
4729
|
`${name}.barOnsets[${index}]`
|
|
4428
4730
|
);
|
|
4429
4731
|
}
|
|
4430
|
-
assertMassDistribution(read.onsetLevels,
|
|
4431
|
-
const barPositions =
|
|
4732
|
+
assertMassDistribution(read.onsetLevels, RHYTHM_LEVEL_COUNT, `${name}.onsetLevels`, onsets === 0);
|
|
4733
|
+
const barPositions = _chunkS3QELJUEcjs.assertArray.call(void 0, read.barPositions, `${name}.barPositions`);
|
|
4432
4734
|
for (let index = 0; index < barPositions.length; index += 1) {
|
|
4433
4735
|
assertBarPositionProfile(barPositions[index], `${name}.barPositions[${index}]`);
|
|
4434
4736
|
}
|
|
@@ -4438,67 +4740,71 @@ function assertRhythmAnalysis(value, name) {
|
|
|
4438
4740
|
`${name}.interOnsetShares`,
|
|
4439
4741
|
onsets === 0
|
|
4440
4742
|
);
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4743
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.restRatio, 0, 1, `${name}.restRatio`);
|
|
4744
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.syncopation, 0, 1, `${name}.syncopation`);
|
|
4745
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.offGridRatio, 0, 1, `${name}.offGridRatio`);
|
|
4444
4746
|
assertString(read.rationale, `${name}.rationale`);
|
|
4445
4747
|
return read;
|
|
4446
4748
|
}
|
|
4447
4749
|
function assertFormSection(value, name, sectionCount) {
|
|
4448
|
-
const read =
|
|
4750
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4449
4751
|
assertString(read.label, `${name}.label`);
|
|
4450
|
-
const startBeat =
|
|
4451
|
-
const endBeat =
|
|
4752
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
4753
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
4452
4754
|
assertSpanOrder(startBeat, endBeat, name);
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4755
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.bars, 0, Number.MAX_SAFE_INTEGER, `${name}.bars`);
|
|
4756
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, read.firstOccurrence, `${name}.firstOccurrence`, 0, Math.max(sectionCount - 1, 0));
|
|
4757
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.similarity, 0, 1, `${name}.similarity`);
|
|
4456
4758
|
assertString(read.rationale, `${name}.rationale`);
|
|
4457
4759
|
return read;
|
|
4458
4760
|
}
|
|
4459
4761
|
function assertReferenceCadence(value, name) {
|
|
4460
|
-
const read =
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4762
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4763
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.atBeat, `${name}.atBeat`);
|
|
4764
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, read.type, CADENCE_TYPES, `${name}.type`);
|
|
4765
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.weight, 0, 1, `${name}.weight`);
|
|
4464
4766
|
return read;
|
|
4465
4767
|
}
|
|
4466
4768
|
function assertReferencePhraseMelody(value, name) {
|
|
4467
|
-
const read =
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
const outline =
|
|
4475
|
-
if (outline.length !==
|
|
4476
|
-
throw new (0,
|
|
4769
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4770
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, read.shape, MELODIC_CONTOUR_SHAPES, `${name}.shape`);
|
|
4771
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, read.low, `${name}.low`);
|
|
4772
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, read.high, `${name}.high`);
|
|
4773
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.mean, 0, MIDI_MAX, `${name}.mean`);
|
|
4774
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.peakPitch, 0, MIDI_MAX, `${name}.peakPitch`);
|
|
4775
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.peakPosition, 0, 1, `${name}.peakPosition`);
|
|
4776
|
+
const outline = _chunkS3QELJUEcjs.assertArray.call(void 0, read.outline, `${name}.outline`);
|
|
4777
|
+
if (outline.length !== PHRASE_OUTLINE_POINTS) {
|
|
4778
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4779
|
+
`${name}.outline must have length ${PHRASE_OUTLINE_POINTS}; received ${outline.length}`
|
|
4780
|
+
);
|
|
4477
4781
|
}
|
|
4478
4782
|
for (let index = 0; index < outline.length; index += 1) {
|
|
4479
|
-
|
|
4783
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, outline[index], `${name}.outline[${index}]`);
|
|
4480
4784
|
}
|
|
4481
|
-
|
|
4482
|
-
|
|
4785
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.onsetDensity, 0, Number.MAX_SAFE_INTEGER, `${name}.onsetDensity`);
|
|
4786
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.restRatio, 0, 1, `${name}.restRatio`);
|
|
4483
4787
|
return read;
|
|
4484
4788
|
}
|
|
4485
|
-
function assertReferencePhrase(value, name, sectionCount, nodeCount) {
|
|
4486
|
-
const read =
|
|
4487
|
-
const startBeat =
|
|
4488
|
-
const endBeat =
|
|
4789
|
+
function assertReferencePhrase(value, name, span, sectionCount, nodeCount) {
|
|
4790
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4791
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
4792
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
4489
4793
|
assertSpanOrder(startBeat, endBeat, name);
|
|
4490
|
-
|
|
4794
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, startBeat, span.startBeat, span.endBeat, `${name}.startBeat`);
|
|
4795
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, endBeat, span.startBeat, span.endBeat, `${name}.endBeat`);
|
|
4796
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.bars, 0, Number.MAX_SAFE_INTEGER, `${name}.bars`);
|
|
4491
4797
|
assertNullable(
|
|
4492
4798
|
read.section,
|
|
4493
4799
|
`${name}.section`,
|
|
4494
|
-
(v, n) =>
|
|
4800
|
+
(v, n) => _chunkS3QELJUEcjs.assertInteger.call(void 0, v, n, 0, Math.max(sectionCount - 1, 0))
|
|
4495
4801
|
);
|
|
4496
|
-
|
|
4802
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.confidence, 0, 1, `${name}.confidence`);
|
|
4497
4803
|
assertNullable(read.cadence, `${name}.cadence`, assertReferenceCadence);
|
|
4498
4804
|
assertNullable(read.melody, `${name}.melody`, assertReferencePhraseMelody);
|
|
4499
|
-
const motifNodes =
|
|
4805
|
+
const motifNodes = _chunkS3QELJUEcjs.assertArray.call(void 0, read.motifNodes, `${name}.motifNodes`);
|
|
4500
4806
|
for (let index = 0; index < motifNodes.length; index += 1) {
|
|
4501
|
-
|
|
4807
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0,
|
|
4502
4808
|
motifNodes[index],
|
|
4503
4809
|
`${name}.motifNodes[${index}]`,
|
|
4504
4810
|
0,
|
|
@@ -4507,74 +4813,80 @@ function assertReferencePhrase(value, name, sectionCount, nodeCount) {
|
|
|
4507
4813
|
}
|
|
4508
4814
|
return read;
|
|
4509
4815
|
}
|
|
4510
|
-
function assertReferenceForm(value, name, nodeCount) {
|
|
4511
|
-
const read =
|
|
4512
|
-
const hypermeter =
|
|
4816
|
+
function assertReferenceForm(value, name, span, nodeCount) {
|
|
4817
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4818
|
+
const hypermeter = _chunkS3QELJUEcjs.assertRecord.call(void 0,
|
|
4513
4819
|
read.hypermeter,
|
|
4514
4820
|
`${name}.hypermeter`
|
|
4515
4821
|
);
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
const sections =
|
|
4822
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, hypermeter.groupBars, 0, Number.MAX_SAFE_INTEGER, `${name}.hypermeter.groupBars`);
|
|
4823
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, hypermeter.confidence, 0, 1, `${name}.hypermeter.confidence`);
|
|
4824
|
+
const sections = _chunkS3QELJUEcjs.assertArray.call(void 0, read.sections, `${name}.sections`);
|
|
4519
4825
|
for (let index = 0; index < sections.length; index += 1) {
|
|
4520
4826
|
assertFormSection(sections[index], `${name}.sections[${index}]`, sections.length);
|
|
4521
4827
|
}
|
|
4522
|
-
const phrases =
|
|
4828
|
+
const phrases = _chunkS3QELJUEcjs.assertArray.call(void 0, read.phrases, `${name}.phrases`);
|
|
4523
4829
|
for (let index = 0; index < phrases.length; index += 1) {
|
|
4524
|
-
assertReferencePhrase(
|
|
4830
|
+
assertReferencePhrase(
|
|
4831
|
+
phrases[index],
|
|
4832
|
+
`${name}.phrases[${index}]`,
|
|
4833
|
+
span,
|
|
4834
|
+
sections.length,
|
|
4835
|
+
nodeCount
|
|
4836
|
+
);
|
|
4525
4837
|
}
|
|
4526
4838
|
return read;
|
|
4527
4839
|
}
|
|
4528
4840
|
function assertResolvedKeyField(value, name) {
|
|
4529
|
-
const read =
|
|
4841
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4530
4842
|
try {
|
|
4531
|
-
|
|
4843
|
+
_chunkYDGMWH43cjs.resolveKey.call(void 0, read);
|
|
4532
4844
|
} catch (error) {
|
|
4533
|
-
if (error instanceof
|
|
4534
|
-
throw new (0,
|
|
4845
|
+
if (error instanceof _chunkS3QELJUEcjs.InvalidInputError) {
|
|
4846
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must be a valid key: ${error.message}`);
|
|
4535
4847
|
}
|
|
4536
4848
|
throw error;
|
|
4537
4849
|
}
|
|
4538
4850
|
return read;
|
|
4539
4851
|
}
|
|
4540
4852
|
function assertReferenceKeyRegion(value, name) {
|
|
4541
|
-
const read =
|
|
4542
|
-
const startBeat =
|
|
4543
|
-
const endBeat =
|
|
4853
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4854
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
4855
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
4544
4856
|
assertSpanOrder(startBeat, endBeat, name);
|
|
4545
4857
|
assertResolvedKeyField(read.key, `${name}.key`);
|
|
4546
|
-
|
|
4858
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.confidence, 0, 1, `${name}.confidence`);
|
|
4547
4859
|
return read;
|
|
4548
4860
|
}
|
|
4549
4861
|
function assertReferenceChord(value, name, keys) {
|
|
4550
|
-
const read =
|
|
4551
|
-
const startBeat =
|
|
4552
|
-
const endBeat =
|
|
4862
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4863
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
4864
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
4553
4865
|
assertSpanOrder(startBeat, endBeat, name);
|
|
4554
|
-
const keyIndex =
|
|
4866
|
+
const keyIndex = _chunkS3QELJUEcjs.assertInteger.call(void 0, read.key, `${name}.key`, 0, Math.max(keys.length - 1, 0));
|
|
4555
4867
|
const roman = assertString(read.roman, `${name}.roman`);
|
|
4556
4868
|
try {
|
|
4557
4869
|
romanToChord(roman, keys[keyIndex]);
|
|
4558
4870
|
} catch (error) {
|
|
4559
|
-
if (error instanceof
|
|
4560
|
-
throw new (0,
|
|
4561
|
-
`${name}.roman must be readable by romanToChord; received ${
|
|
4871
|
+
if (error instanceof _chunkS3QELJUEcjs.InvalidInputError) {
|
|
4872
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4873
|
+
`${name}.roman must be readable by romanToChord; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, roman)}: ${error.message}`
|
|
4562
4874
|
);
|
|
4563
4875
|
}
|
|
4564
4876
|
throw error;
|
|
4565
4877
|
}
|
|
4566
|
-
|
|
4567
|
-
|
|
4878
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, read.function, HARMONIC_FUNCTIONS, `${name}.function`);
|
|
4879
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, read.level, REDUCTION_LEVELS, `${name}.level`);
|
|
4568
4880
|
return read;
|
|
4569
4881
|
}
|
|
4570
4882
|
function assertReferenceHarmony(value, name) {
|
|
4571
|
-
const read =
|
|
4572
|
-
const keys =
|
|
4883
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4884
|
+
const keys = _chunkS3QELJUEcjs.assertArray.call(void 0, read.keys, `${name}.keys`);
|
|
4573
4885
|
for (let index = 0; index < keys.length; index += 1) {
|
|
4574
4886
|
assertReferenceKeyRegion(keys[index], `${name}.keys[${index}]`);
|
|
4575
4887
|
}
|
|
4576
4888
|
const resolvedKeys = keys.map((region) => region.key);
|
|
4577
|
-
const chords =
|
|
4889
|
+
const chords = _chunkS3QELJUEcjs.assertArray.call(void 0, read.chords, `${name}.chords`);
|
|
4578
4890
|
for (let index = 0; index < chords.length; index += 1) {
|
|
4579
4891
|
assertReferenceChord(chords[index], `${name}.chords[${index}]`, resolvedKeys);
|
|
4580
4892
|
}
|
|
@@ -4582,78 +4894,78 @@ function assertReferenceHarmony(value, name) {
|
|
|
4582
4894
|
return read;
|
|
4583
4895
|
}
|
|
4584
4896
|
function assertMotifRelationSummary(value, name) {
|
|
4585
|
-
const read =
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4897
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4898
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, read.kind, MOTIF_RELATION_KINDS, `${name}.kind`);
|
|
4899
|
+
_chunkS3QELJUEcjs.assertFlag.call(void 0, read.sequence, `${name}.sequence`);
|
|
4900
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.semitones, `${name}.semitones`);
|
|
4589
4901
|
if (read.degrees !== void 0) {
|
|
4590
|
-
|
|
4902
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.degrees, `${name}.degrees`);
|
|
4591
4903
|
}
|
|
4592
|
-
const timeRatio =
|
|
4904
|
+
const timeRatio = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.timeRatio, `${name}.timeRatio`);
|
|
4593
4905
|
if (timeRatio <= 0) {
|
|
4594
|
-
throw new (0,
|
|
4906
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}.timeRatio must be positive; received ${timeRatio}`);
|
|
4595
4907
|
}
|
|
4596
4908
|
return read;
|
|
4597
4909
|
}
|
|
4598
4910
|
function assertMotifGraphNode(value, name, occurrenceCounts) {
|
|
4599
|
-
const read =
|
|
4600
|
-
const motif =
|
|
4911
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4912
|
+
const motif = _chunkS3QELJUEcjs.assertInteger.call(void 0,
|
|
4601
4913
|
read.motif,
|
|
4602
4914
|
`${name}.motif`,
|
|
4603
4915
|
0,
|
|
4604
4916
|
Math.max(occurrenceCounts.length - 1, 0)
|
|
4605
4917
|
);
|
|
4606
|
-
|
|
4918
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0,
|
|
4607
4919
|
read.occurrence,
|
|
4608
4920
|
`${name}.occurrence`,
|
|
4609
4921
|
0,
|
|
4610
4922
|
Math.max((_nullishCoalesce(occurrenceCounts[motif], () => ( 1))) - 1, 0)
|
|
4611
4923
|
);
|
|
4612
|
-
const startBeat =
|
|
4613
|
-
const endBeat =
|
|
4924
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
4925
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
4614
4926
|
assertSpanOrder(startBeat, endBeat, name);
|
|
4615
4927
|
return read;
|
|
4616
4928
|
}
|
|
4617
4929
|
function assertMotifGraphEdge(value, name, nodeCount) {
|
|
4618
|
-
const read =
|
|
4619
|
-
const from =
|
|
4620
|
-
const to =
|
|
4930
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4931
|
+
const from = _chunkS3QELJUEcjs.assertInteger.call(void 0, read.from, `${name}.from`, 0, Math.max(nodeCount - 1, 0));
|
|
4932
|
+
const to = _chunkS3QELJUEcjs.assertInteger.call(void 0, read.to, `${name}.to`, 0, Math.max(nodeCount - 1, 0));
|
|
4621
4933
|
if (from >= to) {
|
|
4622
|
-
throw new (0,
|
|
4934
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4623
4935
|
`${name}.from must be less than ${name}.to; received from=${from}, to=${to}`
|
|
4624
4936
|
);
|
|
4625
4937
|
}
|
|
4626
4938
|
assertNullable(read.relation, `${name}.relation`, assertMotifRelationSummary);
|
|
4627
|
-
|
|
4939
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.similarity, 0, 1, `${name}.similarity`);
|
|
4628
4940
|
return read;
|
|
4629
4941
|
}
|
|
4630
4942
|
function assertMotifGraph(value, name, occurrenceCounts) {
|
|
4631
|
-
const read =
|
|
4632
|
-
const nodes =
|
|
4943
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4944
|
+
const nodes = _chunkS3QELJUEcjs.assertArray.call(void 0, read.nodes, `${name}.nodes`);
|
|
4633
4945
|
for (let index = 0; index < nodes.length; index += 1) {
|
|
4634
4946
|
assertMotifGraphNode(nodes[index], `${name}.nodes[${index}]`, occurrenceCounts);
|
|
4635
4947
|
}
|
|
4636
|
-
const edges =
|
|
4948
|
+
const edges = _chunkS3QELJUEcjs.assertArray.call(void 0, read.edges, `${name}.edges`);
|
|
4637
4949
|
const seenTo = /* @__PURE__ */ new Set();
|
|
4638
4950
|
for (let index = 0; index < edges.length; index += 1) {
|
|
4639
4951
|
const edge = assertMotifGraphEdge(edges[index], `${name}.edges[${index}]`, nodes.length);
|
|
4640
4952
|
if (seenTo.has(edge.to)) {
|
|
4641
|
-
throw new (0,
|
|
4953
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}.edges: node ${edge.to} has more than one incoming edge`);
|
|
4642
4954
|
}
|
|
4643
4955
|
seenTo.add(edge.to);
|
|
4644
4956
|
}
|
|
4645
4957
|
return read;
|
|
4646
4958
|
}
|
|
4647
4959
|
function assertReferenceMotif(value, name) {
|
|
4648
|
-
const read =
|
|
4649
|
-
const intervals =
|
|
4960
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4961
|
+
const intervals = _chunkS3QELJUEcjs.assertArray.call(void 0, read.intervals, `${name}.intervals`);
|
|
4650
4962
|
let pitch = 0;
|
|
4651
4963
|
let low = 0;
|
|
4652
4964
|
let high = 0;
|
|
4653
4965
|
for (let index = 0; index < intervals.length; index += 1) {
|
|
4654
|
-
const interval =
|
|
4966
|
+
const interval = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, intervals[index], `${name}.intervals[${index}]`);
|
|
4655
4967
|
if (!Number.isInteger(interval)) {
|
|
4656
|
-
throw new (0,
|
|
4968
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4657
4969
|
`${name}.intervals[${index}] must be a whole number of semitones; received ${interval}`
|
|
4658
4970
|
);
|
|
4659
4971
|
}
|
|
@@ -4661,44 +4973,44 @@ function assertReferenceMotif(value, name) {
|
|
|
4661
4973
|
low = Math.min(low, pitch);
|
|
4662
4974
|
high = Math.max(high, pitch);
|
|
4663
4975
|
}
|
|
4664
|
-
if (high - low >
|
|
4665
|
-
throw new (0,
|
|
4666
|
-
`${name}.intervals must span at most
|
|
4976
|
+
if (high - low > MIDI_MAX) {
|
|
4977
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4978
|
+
`${name}.intervals must span at most ${MIDI_MAX} semitones; received ${high - low}`
|
|
4667
4979
|
);
|
|
4668
4980
|
}
|
|
4669
|
-
const rhythm =
|
|
4981
|
+
const rhythm = _chunkS3QELJUEcjs.assertArray.call(void 0, read.rhythm, `${name}.rhythm`);
|
|
4670
4982
|
if (rhythm.length !== intervals.length) {
|
|
4671
|
-
throw new (0,
|
|
4983
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4672
4984
|
`${name}.rhythm must hold one ratio per interval (${intervals.length}); received ${rhythm.length}`
|
|
4673
4985
|
);
|
|
4674
4986
|
}
|
|
4675
4987
|
for (let index = 0; index < rhythm.length; index += 1) {
|
|
4676
|
-
const ratio2 =
|
|
4988
|
+
const ratio2 = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, rhythm[index], `${name}.rhythm[${index}]`);
|
|
4677
4989
|
if (!(ratio2 > 0)) {
|
|
4678
|
-
throw new (0,
|
|
4990
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}.rhythm[${index}] must be positive; received ${ratio2}`);
|
|
4679
4991
|
}
|
|
4680
4992
|
}
|
|
4681
|
-
const unitBeats =
|
|
4993
|
+
const unitBeats = _chunkS3QELJUEcjs.assertRange.call(void 0, read.unitBeats, 0, Number.MAX_SAFE_INTEGER, `${name}.unitBeats`);
|
|
4682
4994
|
if (unitBeats > 0 !== rhythm.length > 0) {
|
|
4683
|
-
throw new (0,
|
|
4995
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4684
4996
|
`${name}.unitBeats must be positive exactly when rhythm is non-empty; received ${unitBeats} with ${rhythm.length} ratio(s)`
|
|
4685
4997
|
);
|
|
4686
4998
|
}
|
|
4687
|
-
|
|
4688
|
-
|
|
4999
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.spanBeats, 0, Number.MAX_SAFE_INTEGER, `${name}.spanBeats`);
|
|
5000
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, read.occurrences, `${name}.occurrences`);
|
|
4689
5001
|
return read;
|
|
4690
5002
|
}
|
|
4691
5003
|
function assertReferenceMelody(value, name) {
|
|
4692
|
-
const read =
|
|
5004
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4693
5005
|
assertNullable(read.register, `${name}.register`, (v, n) => {
|
|
4694
|
-
const register =
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
5006
|
+
const register = _chunkS3QELJUEcjs.assertRecord.call(void 0, v, n);
|
|
5007
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, register.low, `${n}.low`);
|
|
5008
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, register.high, `${n}.high`);
|
|
5009
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, register.mean, 0, MIDI_MAX, `${n}.mean`);
|
|
4698
5010
|
return register;
|
|
4699
5011
|
});
|
|
4700
|
-
assertNullable(read.shape, `${name}.shape`, (v, n) =>
|
|
4701
|
-
const motifs =
|
|
5012
|
+
assertNullable(read.shape, `${name}.shape`, (v, n) => _chunkS3QELJUEcjs.assertOneOf.call(void 0, v, MELODIC_CONTOUR_SHAPES, n));
|
|
5013
|
+
const motifs = _chunkS3QELJUEcjs.assertArray.call(void 0, read.motifs, `${name}.motifs`);
|
|
4702
5014
|
const occurrenceCounts = [];
|
|
4703
5015
|
for (let index = 0; index < motifs.length; index += 1) {
|
|
4704
5016
|
assertReferenceMotif(motifs[index], `${name}.motifs[${index}]`);
|
|
@@ -4709,23 +5021,23 @@ function assertReferenceMelody(value, name) {
|
|
|
4709
5021
|
return read;
|
|
4710
5022
|
}
|
|
4711
5023
|
function assertReferenceProfile(value, name = "reference profile") {
|
|
4712
|
-
const read =
|
|
5024
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4713
5025
|
if (read.profileVersion !== REFERENCE_PROFILE_VERSION) {
|
|
4714
|
-
throw new (0,
|
|
4715
|
-
`${name}.profileVersion must be ${REFERENCE_PROFILE_VERSION}; received ${
|
|
5026
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
5027
|
+
`${name}.profileVersion must be ${REFERENCE_PROFILE_VERSION}; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, read.profileVersion)}`
|
|
4716
5028
|
);
|
|
4717
5029
|
}
|
|
4718
|
-
const span =
|
|
5030
|
+
const span = _chunkS3QELJUEcjs.assertRecord.call(void 0,
|
|
4719
5031
|
read.span,
|
|
4720
5032
|
`${name}.span`
|
|
4721
5033
|
);
|
|
4722
|
-
const startBeat =
|
|
4723
|
-
const endBeat =
|
|
5034
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, span.startBeat, `${name}.span.startBeat`);
|
|
5035
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, span.endBeat, `${name}.span.endBeat`);
|
|
4724
5036
|
assertSpanOrder(startBeat, endBeat, `${name}.span`);
|
|
4725
|
-
|
|
4726
|
-
|
|
5037
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, span.bars, 0, Number.MAX_SAFE_INTEGER, `${name}.span.bars`);
|
|
5038
|
+
_chunkS3QELJUEcjs.assertMeterMap.call(void 0, read.meters, `${name}.meters`);
|
|
4727
5039
|
const melody = assertReferenceMelody(read.melody, `${name}.melody`);
|
|
4728
|
-
assertReferenceForm(read.form, `${name}.form`, melody.graph.nodes.length);
|
|
5040
|
+
assertReferenceForm(read.form, `${name}.form`, { startBeat, endBeat }, melody.graph.nodes.length);
|
|
4729
5041
|
assertReferenceHarmony(read.harmony, `${name}.harmony`);
|
|
4730
5042
|
return read;
|
|
4731
5043
|
}
|
|
@@ -4742,11 +5054,12 @@ var PEAK_POSITION_WEIGHT = 0.5;
|
|
|
4742
5054
|
var FAMILY_SIZE_BINS = 5;
|
|
4743
5055
|
var DEPTH_BINS = 4;
|
|
4744
5056
|
var NAMED_CHORDS = ["Ger", "It", "Fr", "N"];
|
|
4745
|
-
var
|
|
5057
|
+
var PITCH_PRESERVING_KINDS = [
|
|
4746
5058
|
"repetition",
|
|
4747
5059
|
"augmentation",
|
|
4748
5060
|
"diminution"
|
|
4749
|
-
]
|
|
5061
|
+
];
|
|
5062
|
+
var PITCH_PRESERVING = new Set(PITCH_PRESERVING_KINDS);
|
|
4750
5063
|
var CELL_START_PITCH = 60;
|
|
4751
5064
|
function whenBoth(hasA, hasB, measure) {
|
|
4752
5065
|
if (!hasA && !hasB) {
|
|
@@ -4821,7 +5134,7 @@ function chordCost(x, y) {
|
|
|
4821
5134
|
return x.function === y.function ? SAME_FUNCTION_COST : 1;
|
|
4822
5135
|
}
|
|
4823
5136
|
function progressionSimilarity(a, b, budget) {
|
|
4824
|
-
|
|
5137
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, a.length * b.length, "reference progression alignment", budget);
|
|
4825
5138
|
return alignedSimilarity(a, b, chordCost, PROGRESSION_GAP);
|
|
4826
5139
|
}
|
|
4827
5140
|
function functionMass(chords) {
|
|
@@ -4845,7 +5158,7 @@ function cadenceSimilarity(a, b) {
|
|
|
4845
5158
|
});
|
|
4846
5159
|
}
|
|
4847
5160
|
function keyTokens(keys) {
|
|
4848
|
-
const home = _nullishCoalesce(_optionalChain([keys, 'access',
|
|
5161
|
+
const home = _nullishCoalesce(_optionalChain([keys, 'access', _129 => _129[0], 'optionalAccess', _130 => _130.scale, 'access', _131 => _131.rootPc]), () => ( 0));
|
|
4849
5162
|
return keys.map((key) => ({
|
|
4850
5163
|
distance: ((key.scale.rootPc - home) % 12 + 12) % 12,
|
|
4851
5164
|
mask: key.scale.modeMask12
|
|
@@ -4899,7 +5212,7 @@ function cellNotes(motif) {
|
|
|
4899
5212
|
low = Math.min(low, offset);
|
|
4900
5213
|
high = Math.max(high, offset);
|
|
4901
5214
|
}
|
|
4902
|
-
let pitch = Math.min(
|
|
5215
|
+
let pitch = Math.min(MIDI_MAX - high, Math.max(-low, CELL_START_PITCH));
|
|
4903
5216
|
let beat = 0;
|
|
4904
5217
|
for (let i = 0; i <= motif.intervals.length; i += 1) {
|
|
4905
5218
|
const step = _nullishCoalesce(motif.rhythm[i], () => ( 1));
|
|
@@ -4955,7 +5268,7 @@ function summarise({ graph, spanBeats }) {
|
|
|
4955
5268
|
const kinds = new Array(MOTIF_RELATION_KINDS.length + 1).fill(0);
|
|
4956
5269
|
const parentEdge = /* @__PURE__ */ new Map();
|
|
4957
5270
|
for (const edge of graph.edges) {
|
|
4958
|
-
const kind = _optionalChain([edge, 'access',
|
|
5271
|
+
const kind = _optionalChain([edge, 'access', _132 => _132.relation, 'optionalAccess', _133 => _133.kind]);
|
|
4959
5272
|
bump(
|
|
4960
5273
|
kinds,
|
|
4961
5274
|
kind === void 0 ? MOTIF_RELATION_KINDS.length : MOTIF_RELATION_KINDS.indexOf(kind)
|
|
@@ -4967,7 +5280,7 @@ function summarise({ graph, spanBeats }) {
|
|
|
4967
5280
|
for (let node = 0; node < graph.nodes.length; node += 1) {
|
|
4968
5281
|
const edge = parentEdge.get(node);
|
|
4969
5282
|
if (edge !== void 0) {
|
|
4970
|
-
const kind = _optionalChain([edge, 'access',
|
|
5283
|
+
const kind = _optionalChain([edge, 'access', _134 => _134.relation, 'optionalAccess', _135 => _135.kind]);
|
|
4971
5284
|
const keepsPitch = kind !== void 0 && PITCH_PRESERVING.has(kind);
|
|
4972
5285
|
depth[node] = (_nullishCoalesce(depth[edge.from], () => ( 0))) + (keepsPitch ? 0 : 1);
|
|
4973
5286
|
root[node] = _nullishCoalesce(root[edge.from], () => ( edge.from));
|
|
@@ -5055,7 +5368,7 @@ function weightedMean(notes) {
|
|
|
5055
5368
|
return total > 0 ? weighted / total : 0;
|
|
5056
5369
|
}
|
|
5057
5370
|
function phraseMelody(line, startBeat, endBeat, lineMean, meters, budget) {
|
|
5058
|
-
const inside = line.filter((note) => note.startBeat >= startBeat -
|
|
5371
|
+
const inside = line.filter((note) => note.startBeat >= startBeat - _chunkS3QELJUEcjs.BEAT_EPS && note.startBeat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS).map((note) => ({
|
|
5059
5372
|
...note,
|
|
5060
5373
|
durationBeat: Math.min(note.startBeat + note.durationBeat, endBeat) - note.startBeat
|
|
5061
5374
|
}));
|
|
@@ -5073,18 +5386,18 @@ function phraseMelody(line, startBeat, endBeat, lineMean, meters, budget) {
|
|
|
5073
5386
|
}
|
|
5074
5387
|
const length = endBeat - startBeat;
|
|
5075
5388
|
const outline = [];
|
|
5076
|
-
for (let k = 0; k <
|
|
5077
|
-
const at = startBeat + (k + 0.5) * length /
|
|
5389
|
+
for (let k = 0; k < PHRASE_OUTLINE_POINTS; k += 1) {
|
|
5390
|
+
const at = startBeat + (k + 0.5) * length / PHRASE_OUTLINE_POINTS;
|
|
5078
5391
|
let held = first;
|
|
5079
5392
|
for (const note of inside) {
|
|
5080
|
-
if (note.startBeat > at +
|
|
5393
|
+
if (note.startBeat > at + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5081
5394
|
break;
|
|
5082
5395
|
}
|
|
5083
5396
|
held = note;
|
|
5084
5397
|
}
|
|
5085
5398
|
outline.push(held.pitch - lineMean);
|
|
5086
5399
|
}
|
|
5087
|
-
const rhythm =
|
|
5400
|
+
const rhythm = rhythmOver(inside, { meters, totalBeats: endBeat, budget }, startBeat);
|
|
5088
5401
|
return {
|
|
5089
5402
|
shape: melodicContour(inside).shape,
|
|
5090
5403
|
low,
|
|
@@ -5191,5 +5504,10 @@ function phraseMelody(line, startBeat, endBeat, lineMean, meters, budget) {
|
|
|
5191
5504
|
|
|
5192
5505
|
|
|
5193
5506
|
|
|
5194
|
-
|
|
5195
|
-
|
|
5507
|
+
|
|
5508
|
+
|
|
5509
|
+
|
|
5510
|
+
|
|
5511
|
+
|
|
5512
|
+
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.barSpanOf = barSpanOf; exports.clamp01 = clamp01; exports.floorMod = floorMod; exports.firstSoundingBeat = firstSoundingBeat; exports.resolveSpanEnd = resolveSpanEnd; exports.lastBarOf = lastBarOf; exports.sliceBars = sliceBars; exports.weightSimilarity = weightSimilarity; exports.harmonicNovelty = harmonicNovelty; exports.combineEvidence = combineEvidence; exports.augmentedSixthChord = augmentedSixthChord; exports.augmentedSixthKind = augmentedSixthKind; exports.augmentedSixthFromPitchClasses = augmentedSixthFromPitchClasses; exports.spellAugmentedSixth = spellAugmentedSixth; exports.CADENCE_TYPES = CADENCE_TYPES; exports.detectCadence = detectCadence; exports.isBorrowedChord = isBorrowedChord; exports.borrowedSource = borrowedSource; exports.romanToChord = romanToChord; exports.chordToRoman = chordToRoman; exports.explainRoman = explainRoman; exports.HARMONIC_FUNCTIONS = HARMONIC_FUNCTIONS; 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.gridForNotes = gridForNotes; exports.latestSoundingEnd = latestSoundingEnd; exports.barGridStart = barGridStart; exports.keyTimelineFromNotes = keyTimelineFromNotes; exports.detectModulations = detectModulations; exports.attachPivots = attachPivots; exports.keyLookup = keyLookup; exports.prevailingKeyOf = prevailingKeyOf; exports.toVoiceNotes = toVoiceNotes; exports.analyzeVoice = analyzeVoice; exports.assertChordTimeline = assertChordTimeline; exports.assertSpansInOrder = assertSpansInOrder; exports.statedKeyRegions = statedKeyRegions; exports.chordTimelineFromChords = chordTimelineFromChords; exports.chordAtBeat = chordAtBeat; exports.segmentStartingAt = segmentStartingAt; exports.chordTimelineFromNotes = chordTimelineFromNotes; exports.dirtySlotsFor = dirtySlotsFor; exports.analyzeTimeline = analyzeTimeline; exports.detectCadences = detectCadences; exports.orderedNotes = orderedNotes; exports.MELODIC_CONTOUR_SHAPES = MELODIC_CONTOUR_SHAPES; exports.melodicContour = melodicContour; exports.extractMotifs = extractMotifs; exports.motifFromNotes = motifFromNotes; exports.MOTIF_RELATION_KINDS = MOTIF_RELATION_KINDS; exports.relateMotifs = relateMotifs; exports.compareMelodies = compareMelodies; exports.melodicSimilarity = melodicSimilarity; exports.DEFAULT_VARIATION_THRESHOLD = DEFAULT_VARIATION_THRESHOLD; exports.motifGraph = motifGraph; exports.REDUCTION_LEVELS = REDUCTION_LEVELS; exports.reduceProgression = reduceProgression; exports.REFERENCE_PROFILE_VERSION = REFERENCE_PROFILE_VERSION; exports.sectionSequenceSimilarity = sectionSequenceSimilarity; exports.phraseLengthSimilarity = phraseLengthSimilarity; exports.progressionSimilarity = progressionSimilarity; exports.functionSimilarity = functionSimilarity; exports.cadenceSimilarity = cadenceSimilarity; exports.keyPlanSimilarity = keyPlanSimilarity; exports.onsetSimilarity = onsetSimilarity; exports.densitySimilarity = densitySimilarity; exports.durationSimilarity = durationSimilarity; exports.syncopationSimilarity = syncopationSimilarity; exports.surfaceSimilarity = surfaceSimilarity; exports.motifStructureSimilarity = motifStructureSimilarity; exports.contourSimilarity = contourSimilarity; exports.registerSimilarity = registerSimilarity; exports.rhythmLevel = rhythmLevel; exports.ioiBinIndex = ioiBinIndex; exports.RHYTHM_IOI_BINS = RHYTHM_IOI_BINS; exports.analyzeRhythm = analyzeRhythm; exports.rhythmOver = rhythmOver; exports.assertReferenceProfile = assertReferenceProfile; exports.weightedMean = weightedMean; exports.phraseMelody = phraseMelody;
|
|
5513
|
+
//# sourceMappingURL=chunk-LQZQDBCD.cjs.map
|