@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
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
var _chunkLQZQDBCDcjs = require('./chunk-LQZQDBCD.cjs');
|
|
32
33
|
|
|
33
|
-
var _chunkIFZDWIKMcjs = require('./chunk-IFZDWIKM.cjs');
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
|
|
@@ -43,16 +43,16 @@ var _chunkIFZDWIKMcjs = require('./chunk-IFZDWIKM.cjs');
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
var
|
|
46
|
+
var _chunkWOMCXN2Wcjs = require('./chunk-WOMCXN2W.cjs');
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
var _chunk35NBV2FTcjs = require('./chunk-35NBV2FT.cjs');
|
|
50
49
|
|
|
51
50
|
|
|
51
|
+
var _chunkKMYGRFZ6cjs = require('./chunk-KMYGRFZ6.cjs');
|
|
52
52
|
|
|
53
|
-
var _chunkPM4XJE2Ycjs = require('./chunk-PM4XJE2Y.cjs');
|
|
54
53
|
|
|
55
54
|
|
|
55
|
+
var _chunkP3CPXAJ5cjs = require('./chunk-P3CPXAJ5.cjs');
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
|
|
@@ -84,10 +84,10 @@ var _chunkPM4XJE2Ycjs = require('./chunk-PM4XJE2Y.cjs');
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
|
|
87
|
-
var _chunk3R3QVKY5cjs = require('./chunk-3R3QVKY5.cjs');
|
|
88
87
|
|
|
89
88
|
|
|
90
89
|
|
|
90
|
+
var _chunkYDGMWH43cjs = require('./chunk-YDGMWH43.cjs');
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
|
|
@@ -130,24 +130,28 @@ var _chunk3R3QVKY5cjs = require('./chunk-3R3QVKY5.cjs');
|
|
|
130
130
|
|
|
131
131
|
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
var _chunkS3QELJUEcjs = require('./chunk-S3QELJUE.cjs');
|
|
134
138
|
|
|
135
139
|
// src/generate/context/draw.ts
|
|
136
140
|
var DRAW_METHODS = ["at", "prob", "range", "float"];
|
|
137
141
|
function assertDraw(draw, name = "draw") {
|
|
138
|
-
const sampler =
|
|
142
|
+
const sampler = _chunkS3QELJUEcjs.assertRecord.call(void 0, draw, name);
|
|
139
143
|
for (const method of DRAW_METHODS) {
|
|
140
|
-
|
|
144
|
+
_chunkS3QELJUEcjs.assertFunction.call(void 0, sampler[method], `${name}.${method}`);
|
|
141
145
|
}
|
|
142
146
|
return sampler;
|
|
143
147
|
}
|
|
144
148
|
function assertSeedPath(path, name = "draw path") {
|
|
145
|
-
const steps =
|
|
149
|
+
const steps = _chunkS3QELJUEcjs.assertArray.call(void 0, path, name);
|
|
146
150
|
for (let index = 0; index < steps.length; index += 1) {
|
|
147
151
|
const step = steps[index];
|
|
148
152
|
if (typeof step !== "string" && !Number.isFinite(step)) {
|
|
149
|
-
throw new (0,
|
|
150
|
-
`${name}[${index}] must be a string or a finite number; received ${
|
|
153
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
154
|
+
`${name}[${index}] must be a string or a finite number; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, step)}`
|
|
151
155
|
);
|
|
152
156
|
}
|
|
153
157
|
}
|
|
@@ -156,7 +160,7 @@ function assertSeedPath(path, name = "draw path") {
|
|
|
156
160
|
function drawFrom(rng, path) {
|
|
157
161
|
const draw = rng.at(...path);
|
|
158
162
|
if (!(draw >= 0 && draw < 1)) {
|
|
159
|
-
throw new (0,
|
|
163
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`positional draw must be in [0, 1); received ${draw}`);
|
|
160
164
|
}
|
|
161
165
|
return draw;
|
|
162
166
|
}
|
|
@@ -164,28 +168,28 @@ function drawsFrom(rng, ...prefix) {
|
|
|
164
168
|
const at2 = (...path) => drawFrom(rng, [...prefix, ...path]);
|
|
165
169
|
return {
|
|
166
170
|
at: at2,
|
|
167
|
-
prob: (p, ...path) =>
|
|
171
|
+
prob: (p, ...path) => _chunkWOMCXN2Wcjs.includeAt.call(void 0, rng, p, ...prefix, ...path),
|
|
168
172
|
range: (lo, hi, ...path) => {
|
|
169
|
-
|
|
170
|
-
|
|
173
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, lo, "range lower bound");
|
|
174
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, hi, "range upper bound");
|
|
171
175
|
if (lo > hi) {
|
|
172
|
-
throw new (0,
|
|
176
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
173
177
|
`range lower bound must not exceed upper bound; received ${lo} > ${hi}`
|
|
174
178
|
);
|
|
175
179
|
}
|
|
176
|
-
|
|
180
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, hi - lo, "range span", 0);
|
|
177
181
|
return lo + Math.floor(at2(...path) * (hi - lo + 1));
|
|
178
182
|
},
|
|
179
183
|
float: (lo, hi, ...path) => {
|
|
180
|
-
|
|
181
|
-
|
|
184
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, lo, "float lower bound");
|
|
185
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, hi, "float upper bound");
|
|
182
186
|
if (lo > hi) {
|
|
183
|
-
throw new (0,
|
|
187
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
184
188
|
`float lower bound must not exceed upper bound; received ${lo} > ${hi}`
|
|
185
189
|
);
|
|
186
190
|
}
|
|
187
|
-
|
|
188
|
-
return
|
|
191
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, hi - lo, "float span");
|
|
192
|
+
return _chunkWOMCXN2Wcjs.scaleUnitDraw.call(void 0, at2(...path), lo, hi);
|
|
189
193
|
}
|
|
190
194
|
};
|
|
191
195
|
}
|
|
@@ -410,11 +414,13 @@ var GENRES = Object.freeze([
|
|
|
410
414
|
]);
|
|
411
415
|
var PROVENANCE_BASES = Object.freeze(["idiom", "construction", "traditional"]);
|
|
412
416
|
function sameTs(a, b) {
|
|
413
|
-
|
|
417
|
+
const grouping = a.grouping;
|
|
418
|
+
const theirs = b.grouping;
|
|
419
|
+
return a.numerator === b.numerator && a.denominator === b.denominator && (grouping === void 0 || theirs === void 0 ? grouping === theirs : Array.isArray(grouping) && grouping.length === theirs.length && grouping.every((entry, index) => entry === theirs[index]));
|
|
414
420
|
}
|
|
415
421
|
function fitsQuery(entry, query) {
|
|
416
|
-
const candidate =
|
|
417
|
-
const asked =
|
|
422
|
+
const candidate = _chunkS3QELJUEcjs.assertRecord.call(void 0, entry, "vocabulary entry");
|
|
423
|
+
const asked = _chunkS3QELJUEcjs.assertRecord.call(void 0, query, "vocabulary query");
|
|
418
424
|
if (asked.genre !== void 0 && candidate.genre !== asked.genre) {
|
|
419
425
|
return false;
|
|
420
426
|
}
|
|
@@ -427,7 +433,7 @@ function fitsQuery(entry, query) {
|
|
|
427
433
|
return false;
|
|
428
434
|
}
|
|
429
435
|
}
|
|
430
|
-
if (asked.ts !== void 0 && candidate.ts && !sameTs(candidate.ts,
|
|
436
|
+
if (asked.ts !== void 0 && candidate.ts && !sameTs(candidate.ts, _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, asked.ts, "ts")))) {
|
|
431
437
|
return false;
|
|
432
438
|
}
|
|
433
439
|
if (asked.quality !== void 0 && candidate.fitsOver && !candidate.fitsOver.includes(asked.quality)) {
|
|
@@ -442,7 +448,7 @@ function fitsQuery(entry, query) {
|
|
|
442
448
|
return asked.difficulty === void 0 || candidate.difficulty <= asked.difficulty;
|
|
443
449
|
}
|
|
444
450
|
function selectVocabulary(dictionary, query) {
|
|
445
|
-
return
|
|
451
|
+
return _chunkS3QELJUEcjs.assertArray.call(void 0, dictionary, "dictionary").filter(
|
|
446
452
|
(entry) => fitsQuery(entry, query)
|
|
447
453
|
);
|
|
448
454
|
}
|
|
@@ -456,12 +462,12 @@ function pickVocabulary(dictionary, query, draw, ...path) {
|
|
|
456
462
|
return candidates[sampler.range(0, candidates.length - 1, ...path)];
|
|
457
463
|
}
|
|
458
464
|
function mergeVocabulary(builtIn, supplied) {
|
|
459
|
-
const library =
|
|
460
|
-
const extra = supplied === void 0 || supplied === null ? [] :
|
|
465
|
+
const library = _chunkS3QELJUEcjs.assertArray.call(void 0, builtIn, "builtIn");
|
|
466
|
+
const extra = supplied === void 0 || supplied === null ? [] : _chunkS3QELJUEcjs.assertArray.call(void 0, supplied, "supplied");
|
|
461
467
|
if (extra.length === 0) {
|
|
462
468
|
return [...library];
|
|
463
469
|
}
|
|
464
|
-
const idOf = (entry, index, side) =>
|
|
470
|
+
const idOf = (entry, index, side) => _chunkS3QELJUEcjs.assertRecord.call(void 0, entry, `${side}[${index}]`).id;
|
|
465
471
|
const byId = new Map(extra.map((entry, index) => [idOf(entry, index, "supplied"), entry]));
|
|
466
472
|
const merged = library.map((entry, index) => _nullishCoalesce(byId.get(idOf(entry, index, "builtIn")), () => ( entry)));
|
|
467
473
|
const replaced = new Set(library.map((entry, index) => idOf(entry, index, "builtIn")));
|
|
@@ -474,9 +480,9 @@ function mergeVocabulary(builtIn, supplied) {
|
|
|
474
480
|
}
|
|
475
481
|
function vocabularyOfKind(entries, isMaterial) {
|
|
476
482
|
const out = [];
|
|
477
|
-
const recognises =
|
|
478
|
-
for (const entry of
|
|
479
|
-
if (recognises(
|
|
483
|
+
const recognises = _chunkS3QELJUEcjs.assertFunction.call(void 0, isMaterial, "isMaterial");
|
|
484
|
+
for (const entry of _chunkS3QELJUEcjs.assertArray.call(void 0, entries, "entries")) {
|
|
485
|
+
if (recognises(_chunkS3QELJUEcjs.assertRecord.call(void 0, entry, "entry").material)) {
|
|
480
486
|
out.push(entry);
|
|
481
487
|
}
|
|
482
488
|
}
|
|
@@ -484,42 +490,42 @@ function vocabularyOfKind(entries, isMaterial) {
|
|
|
484
490
|
}
|
|
485
491
|
function assertNames(values, allowed, label) {
|
|
486
492
|
if (!Array.isArray(values)) {
|
|
487
|
-
throw new (0,
|
|
488
|
-
`${label} must be an array of names; received ${
|
|
493
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
494
|
+
`${label} must be an array of names; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, values)}`
|
|
489
495
|
);
|
|
490
496
|
}
|
|
491
497
|
values.forEach((value, index) => {
|
|
492
|
-
|
|
498
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, value, allowed, `${label}[${index}]`);
|
|
493
499
|
});
|
|
494
500
|
}
|
|
495
501
|
function assertVocabulary(entry, label = "vocabulary entry") {
|
|
496
502
|
if (typeof entry !== "object" || entry === null) {
|
|
497
|
-
throw new (0,
|
|
498
|
-
`${label} must be a dictionary entry; received ${
|
|
503
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
504
|
+
`${label} must be a dictionary entry; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, entry)}`
|
|
499
505
|
);
|
|
500
506
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
assertNames(entry.articulations,
|
|
507
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, entry.genre, GENRES, `${label} genre`);
|
|
508
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, _optionalChain([entry, 'access', _2 => _2.provenance, 'optionalAccess', _3 => _3.basis]), PROVENANCE_BASES, `${label} provenance basis`);
|
|
509
|
+
assertNames(entry.articulations, _chunkS3QELJUEcjs.ARTICULATIONS, `${label} articulations`);
|
|
504
510
|
if (entry.sections !== void 0) {
|
|
505
511
|
assertNames(entry.sections, PUBLIC_SECTIONS, `${label} sections`);
|
|
506
512
|
}
|
|
507
513
|
if (entry.fitsOver !== void 0) {
|
|
508
|
-
assertNames(entry.fitsOver,
|
|
514
|
+
assertNames(entry.fitsOver, _chunkYDGMWH43cjs.chordQualities.call(void 0, ), `${label} fitsOver`);
|
|
509
515
|
}
|
|
510
516
|
if (entry.ts !== void 0) {
|
|
511
|
-
|
|
517
|
+
_chunkS3QELJUEcjs.assertTimeSignature.call(void 0, entry.ts, `${label} ts`);
|
|
512
518
|
}
|
|
513
|
-
|
|
519
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, entry.difficulty, 1, 5, `${label} difficulty`);
|
|
514
520
|
if (entry.tempoRange !== void 0) {
|
|
515
521
|
if (!Array.isArray(entry.tempoRange) || entry.tempoRange.length !== 2) {
|
|
516
|
-
throw new (0,
|
|
517
|
-
`${label} tempoRange must be a low and a high tempo; received ${
|
|
522
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
523
|
+
`${label} tempoRange must be a low and a high tempo; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, entry.tempoRange)}`
|
|
518
524
|
);
|
|
519
525
|
}
|
|
520
526
|
const [low, high] = entry.tempoRange;
|
|
521
|
-
|
|
522
|
-
|
|
527
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, low, Number.MIN_VALUE, 1e3, `${label} tempoRange low`);
|
|
528
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, high, low, 1e3, `${label} tempoRange high`);
|
|
523
529
|
}
|
|
524
530
|
return entry;
|
|
525
531
|
}
|
|
@@ -541,15 +547,15 @@ function atLevel(table, difficulty) {
|
|
|
541
547
|
return low + (high - low) * (level - lower);
|
|
542
548
|
}
|
|
543
549
|
function assertDifficulty(difficulty, label = "complexity difficulty") {
|
|
544
|
-
return
|
|
550
|
+
return _chunkS3QELJUEcjs.assertRange.call(void 0, difficulty, MIN_DIFFICULTY, MAX_DIFFICULTY, label);
|
|
545
551
|
}
|
|
546
552
|
function sustainsStrokes(stepBeats, bpm, difficulty) {
|
|
547
553
|
if (difficulty === void 0 || bpm === void 0) {
|
|
548
554
|
return true;
|
|
549
555
|
}
|
|
550
556
|
assertDifficulty(difficulty);
|
|
551
|
-
|
|
552
|
-
if (
|
|
557
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, bpm, "bpm");
|
|
558
|
+
if (_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, stepBeats, "stepBeats") <= 0) {
|
|
553
559
|
return true;
|
|
554
560
|
}
|
|
555
561
|
const rate = 1 / (stepBeats * secondsPerBeat(bpm));
|
|
@@ -560,9 +566,9 @@ function sustainsShift(semitones, stepBeats, bpm, difficulty) {
|
|
|
560
566
|
return true;
|
|
561
567
|
}
|
|
562
568
|
assertDifficulty(difficulty);
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
if (
|
|
569
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, bpm, "bpm");
|
|
570
|
+
_chunkS3QELJUEcjs.assertFiniteSemitones.call(void 0, semitones);
|
|
571
|
+
if (_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, stepBeats, "stepBeats") <= 0) {
|
|
566
572
|
return true;
|
|
567
573
|
}
|
|
568
574
|
const seconds = stepBeats * secondsPerBeat(bpm);
|
|
@@ -571,28 +577,34 @@ function sustainsShift(semitones, stepBeats, bpm, difficulty) {
|
|
|
571
577
|
|
|
572
578
|
// src/generate/context/index.ts
|
|
573
579
|
var DEFAULT_SEED = 0;
|
|
580
|
+
function nullish(value) {
|
|
581
|
+
return value === void 0 || value === null;
|
|
582
|
+
}
|
|
583
|
+
function assertPositionalSource(rng) {
|
|
584
|
+
const source = _chunkS3QELJUEcjs.assertRecord.call(void 0, rng, "ctx.rng");
|
|
585
|
+
_chunkS3QELJUEcjs.assertFunction.call(void 0, source.at, "ctx.rng.at");
|
|
586
|
+
return source;
|
|
587
|
+
}
|
|
574
588
|
var VERSION_SEGMENT = "v";
|
|
575
589
|
function resolveContext(input) {
|
|
576
590
|
if (input !== null && typeof input !== "number" && input !== void 0) {
|
|
577
|
-
|
|
591
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, input, "ctx");
|
|
578
592
|
}
|
|
579
593
|
if (input === null) {
|
|
580
|
-
throw new (0,
|
|
594
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("ctx must be a seed or a generation context; received null");
|
|
581
595
|
}
|
|
582
596
|
const ctx = typeof input === "number" ? { seed: input } : _nullishCoalesce(input, () => ( { seed: DEFAULT_SEED }));
|
|
583
|
-
const seed =
|
|
584
|
-
const complexity =
|
|
585
|
-
const rhythmic = complexity.rhythmic === void 0 ? void 0 :
|
|
586
|
-
const harmonic = complexity.harmonic === void 0 ? void 0 :
|
|
587
|
-
const ornament2 = complexity.ornament === void 0 ? void 0 :
|
|
597
|
+
const seed = _chunkS3QELJUEcjs.assertInteger.call(void 0, _nullishCoalesce(ctx.seed, () => ( DEFAULT_SEED)), "seed", 0, 4294967295);
|
|
598
|
+
const complexity = nullish(ctx.complexity) ? {} : _chunkS3QELJUEcjs.assertRecord.call(void 0, ctx.complexity, "ctx.complexity");
|
|
599
|
+
const rhythmic = complexity.rhythmic === void 0 ? void 0 : _chunkS3QELJUEcjs.assertRange.call(void 0, complexity.rhythmic, 0, 1, "complexity rhythmic");
|
|
600
|
+
const harmonic = complexity.harmonic === void 0 ? void 0 : _chunkS3QELJUEcjs.assertRange.call(void 0, complexity.harmonic, 0, 1, "complexity harmonic");
|
|
601
|
+
const ornament2 = complexity.ornament === void 0 ? void 0 : _chunkS3QELJUEcjs.assertRange.call(void 0, complexity.ornament, 0, 1, "complexity ornament");
|
|
588
602
|
const difficulty = complexity.difficulty === void 0 ? void 0 : assertDifficulty(complexity.difficulty);
|
|
589
|
-
const bpm = ctx.bpm === void 0 ? void 0 :
|
|
590
|
-
const algorithmVersion =
|
|
591
|
-
const supplied = ctx.rng;
|
|
592
|
-
const instruments = ctx.instruments;
|
|
593
|
-
const vocabulary = (
|
|
594
|
-
(entry, index) => assertVocabulary(entry, `vocabulary[${index}]`)
|
|
595
|
-
);
|
|
603
|
+
const bpm = ctx.bpm === void 0 ? void 0 : _chunkS3QELJUEcjs.assertRange.call(void 0, ctx.bpm, Number.MIN_VALUE, 1e3, "bpm");
|
|
604
|
+
const algorithmVersion = _chunkWOMCXN2Wcjs.resolveAlgorithmVersion.call(void 0, ctx.algorithmVersion);
|
|
605
|
+
const supplied = ctx.rng ? assertPositionalSource(ctx.rng) : void 0;
|
|
606
|
+
const instruments = nullish(ctx.instruments) ? void 0 : _chunkS3QELJUEcjs.assertRecord.call(void 0, ctx.instruments, "ctx.instruments");
|
|
607
|
+
const vocabulary = (nullish(ctx.vocabulary) ? [] : _chunkS3QELJUEcjs.assertArray.call(void 0, ctx.vocabulary, "ctx.vocabulary")).map((entry, index) => assertVocabulary(entry, `vocabulary[${index}]`));
|
|
596
608
|
return {
|
|
597
609
|
seed,
|
|
598
610
|
rhythmic,
|
|
@@ -601,14 +613,14 @@ function resolveContext(input) {
|
|
|
601
613
|
difficulty,
|
|
602
614
|
bpm,
|
|
603
615
|
algorithmVersion,
|
|
604
|
-
instrument: (part) =>
|
|
616
|
+
instrument: (part) => instruments !== void 0 && Object.hasOwn(instruments, part) ? instruments[part] : void 0,
|
|
605
617
|
vocabulary,
|
|
606
|
-
part: (name) => supplied ? drawsFrom(supplied, name, VERSION_SEGMENT, algorithmVersion) : drawsFrom(
|
|
618
|
+
part: (name) => supplied ? drawsFrom(supplied, name, VERSION_SEGMENT, algorithmVersion) : drawsFrom(_chunkWOMCXN2Wcjs.createPositionalRng.call(void 0, _chunkWOMCXN2Wcjs.deriveSeed.call(void 0, seed, name, VERSION_SEGMENT, algorithmVersion)))
|
|
607
619
|
};
|
|
608
620
|
}
|
|
609
621
|
function resolveContextWith(input, sugar) {
|
|
610
622
|
const base = resolveContext(input);
|
|
611
|
-
const supplied = sugar.ornament === void 0 ? void 0 :
|
|
623
|
+
const supplied = sugar.ornament === void 0 ? void 0 : _chunkS3QELJUEcjs.assertRange.call(void 0, sugar.ornament, 0, 1, "complexity ornament");
|
|
612
624
|
const ornament2 = _nullishCoalesce(base.ornament, () => ( supplied));
|
|
613
625
|
return { ...base, ornament: ornament2 };
|
|
614
626
|
}
|
|
@@ -625,14 +637,14 @@ function placeAboveBass(pc, bassMidi) {
|
|
|
625
637
|
return foldIntoBand(pc + 12 * Math.round((bassMidi - pc) / 12), bassMidi);
|
|
626
638
|
}
|
|
627
639
|
function placeRoot(pc, low) {
|
|
628
|
-
return low +
|
|
640
|
+
return low + _chunkS3QELJUEcjs.pitchClassOf.call(void 0, pc - low);
|
|
629
641
|
}
|
|
630
642
|
function barTiles(startBeat, endBeat, ts) {
|
|
631
|
-
const barBeats =
|
|
643
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts);
|
|
632
644
|
const tiles = [];
|
|
633
645
|
for (let index = 0; ; index += 1) {
|
|
634
646
|
const tileStart = startBeat + index * barBeats;
|
|
635
|
-
if (tileStart >= endBeat -
|
|
647
|
+
if (tileStart >= endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
636
648
|
break;
|
|
637
649
|
}
|
|
638
650
|
tiles.push({ startBeat: tileStart, endBeat: Math.min(tileStart + barBeats, endBeat) });
|
|
@@ -640,8 +652,8 @@ function barTiles(startBeat, endBeat, ts) {
|
|
|
640
652
|
return tiles;
|
|
641
653
|
}
|
|
642
654
|
function midBarPulse(barStart, ts) {
|
|
643
|
-
const pulse2 =
|
|
644
|
-
return barStart + Math.floor((
|
|
655
|
+
const pulse2 = _chunkS3QELJUEcjs.pulseBeats.call(void 0, ts);
|
|
656
|
+
return barStart + Math.floor((_chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts) / 2 + _chunkS3QELJUEcjs.BEAT_EPS) / pulse2) * pulse2;
|
|
645
657
|
}
|
|
646
658
|
function assertBassSegments(segments) {
|
|
647
659
|
for (let index = 0; index < segments.length; index += 1) {
|
|
@@ -649,14 +661,14 @@ function assertBassSegments(segments) {
|
|
|
649
661
|
if (segment === void 0) {
|
|
650
662
|
continue;
|
|
651
663
|
}
|
|
652
|
-
|
|
653
|
-
|
|
664
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, segment.startBeat, 0, Number.MAX_SAFE_INTEGER, `segments[${index}].startBeat`);
|
|
665
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, segment.endBeat, 0, Number.MAX_SAFE_INTEGER, `segments[${index}].endBeat`);
|
|
654
666
|
if (segment.endBeat <= segment.startBeat) {
|
|
655
|
-
throw new (0,
|
|
667
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`segments[${index}] must have a positive duration`);
|
|
656
668
|
}
|
|
657
669
|
const previous = segments[index - 1];
|
|
658
|
-
if (previous !== void 0 && segment.startBeat < previous.endBeat -
|
|
659
|
-
throw new (0,
|
|
670
|
+
if (previous !== void 0 && segment.startBeat < previous.endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
671
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
660
672
|
`bass segments must not overlap: segments ${index - 1} and ${index} overlap`
|
|
661
673
|
);
|
|
662
674
|
}
|
|
@@ -666,22 +678,22 @@ function chordTonePcs(chord) {
|
|
|
666
678
|
const seen = /* @__PURE__ */ new Set();
|
|
667
679
|
const pcs = [];
|
|
668
680
|
for (const interval of chord.intervals) {
|
|
669
|
-
const pc =
|
|
681
|
+
const pc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc + interval);
|
|
670
682
|
if (!seen.has(pc)) {
|
|
671
683
|
seen.add(pc);
|
|
672
684
|
pcs.push(pc);
|
|
673
685
|
}
|
|
674
686
|
}
|
|
675
687
|
if (pcs.length === 0) {
|
|
676
|
-
pcs.push(
|
|
688
|
+
pcs.push(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc));
|
|
677
689
|
}
|
|
678
690
|
return pcs;
|
|
679
691
|
}
|
|
680
692
|
function fifthPcOf2(chord) {
|
|
681
|
-
return _nullishCoalesce(
|
|
693
|
+
return _nullishCoalesce(_chunkYDGMWH43cjs.fifthPcOf.call(void 0, chord), () => ( _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc)));
|
|
682
694
|
}
|
|
683
695
|
function bassPcOf(chord) {
|
|
684
|
-
return
|
|
696
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, _nullishCoalesce(chord.bassPc, () => ( chord.rootPc)));
|
|
685
697
|
}
|
|
686
698
|
function bassToneCycle(chord) {
|
|
687
699
|
const bass = bassPcOf(chord);
|
|
@@ -691,19 +703,19 @@ function bassToneCycle(chord) {
|
|
|
691
703
|
}
|
|
692
704
|
function beatPositions(start, end, ts) {
|
|
693
705
|
const positions = [];
|
|
694
|
-
const barBeats =
|
|
695
|
-
const pulse2 =
|
|
706
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts);
|
|
707
|
+
const pulse2 = _chunkS3QELJUEcjs.pulseBeats.call(void 0, ts);
|
|
696
708
|
const firstBar = Math.floor(start / barBeats);
|
|
697
|
-
const lastBar = Math.floor((end -
|
|
709
|
+
const lastBar = Math.floor((end - _chunkS3QELJUEcjs.BEAT_EPS) / barBeats);
|
|
698
710
|
for (let bar2 = firstBar; bar2 <= lastBar; bar2 += 1) {
|
|
699
711
|
const barStart = bar2 * barBeats;
|
|
700
|
-
const firstPulse = Math.max(0, Math.ceil((start - barStart -
|
|
712
|
+
const firstPulse = Math.max(0, Math.ceil((start - barStart - _chunkS3QELJUEcjs.BEAT_EPS) / pulse2));
|
|
701
713
|
for (let index = firstPulse; ; index += 1) {
|
|
702
714
|
const position = barStart + index * pulse2;
|
|
703
|
-
if (position >= barStart + barBeats -
|
|
715
|
+
if (position >= barStart + barBeats - _chunkS3QELJUEcjs.BEAT_EPS || position >= end - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
704
716
|
break;
|
|
705
717
|
}
|
|
706
|
-
if (position >= start -
|
|
718
|
+
if (position >= start - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
707
719
|
positions.push(position);
|
|
708
720
|
}
|
|
709
721
|
}
|
|
@@ -721,7 +733,7 @@ function bandFloor(low, instrument) {
|
|
|
721
733
|
if (!instrument) {
|
|
722
734
|
return low;
|
|
723
735
|
}
|
|
724
|
-
const range =
|
|
736
|
+
const range = _chunkWOMCXN2Wcjs.instrumentRange.call(void 0, instrument);
|
|
725
737
|
const dropped = low - 12 * Math.max(0, Math.ceil((low + 12 - range.high) / 12));
|
|
726
738
|
return dropped + 12 * Math.max(0, Math.ceil((range.low - dropped) / 12));
|
|
727
739
|
}
|
|
@@ -740,12 +752,12 @@ function neighborOnSide(target, dir, key, chromatic) {
|
|
|
740
752
|
if (chromatic) {
|
|
741
753
|
return semitone;
|
|
742
754
|
}
|
|
743
|
-
const cand =
|
|
755
|
+
const cand = _chunkYDGMWH43cjs.nearestScaleTone.call(void 0, target + dir * 2, key);
|
|
744
756
|
const step = Math.abs(cand - target);
|
|
745
757
|
return step >= 1 && step <= 2 ? cand : semitone;
|
|
746
758
|
}
|
|
747
759
|
function bassRegister(named, given, octave) {
|
|
748
|
-
const instrument = given === void 0 ? named !== void 0 && named.kind === "stringed" ? named : void 0 :
|
|
760
|
+
const instrument = given === void 0 ? named !== void 0 && named.kind === "stringed" ? named : void 0 : _chunkWOMCXN2Wcjs.toStringedProfile.call(void 0, given, "instrument");
|
|
749
761
|
return { instrument, low: bandFloor(octave * 12 + 12, instrument) };
|
|
750
762
|
}
|
|
751
763
|
|
|
@@ -753,32 +765,43 @@ function bassRegister(named, given, octave) {
|
|
|
753
765
|
var BAR_STEPS = 16;
|
|
754
766
|
var BEAT_STEPS = 4;
|
|
755
767
|
var STEP_BEATS = 1 / BEAT_STEPS;
|
|
768
|
+
var FIGURE_RATES = ["straight", "half", "double"];
|
|
756
769
|
function assertGridEvents(events) {
|
|
757
|
-
|
|
770
|
+
_chunkS3QELJUEcjs.assertArray.call(void 0, events, "figure events");
|
|
758
771
|
events.forEach((event, index) => {
|
|
759
|
-
|
|
760
|
-
|
|
772
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, event, `figure events[${index}]`);
|
|
773
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, event.step, `figure events[${index}].step`);
|
|
761
774
|
});
|
|
762
775
|
return events;
|
|
763
776
|
}
|
|
764
777
|
function assertSpanSteps(spanSteps) {
|
|
765
|
-
return
|
|
778
|
+
return _chunkS3QELJUEcjs.assertPositiveInt.call(void 0, spanSteps, "figure span steps");
|
|
766
779
|
}
|
|
767
780
|
function streamOf(event) {
|
|
768
781
|
return _nullishCoalesce(_nullishCoalesce(event.limb, () => ( event.voice)), () => ( ""));
|
|
769
782
|
}
|
|
783
|
+
function positionKey(event, step) {
|
|
784
|
+
return `${streamOf(event)}@${step}`;
|
|
785
|
+
}
|
|
786
|
+
function drawKey(event) {
|
|
787
|
+
const stream = `${streamOf(event)}`;
|
|
788
|
+
return stream === "" ? [event.step] : [stream, event.step];
|
|
789
|
+
}
|
|
790
|
+
function halvedStep(step) {
|
|
791
|
+
return Number.isInteger(step) ? Math.round(step / 2) : step / 2;
|
|
792
|
+
}
|
|
770
793
|
var FIGURE_TS = { numerator: 4, denominator: 4 };
|
|
771
794
|
function subdivisionBeats(ts) {
|
|
772
|
-
const pulse2 =
|
|
773
|
-
return
|
|
795
|
+
const pulse2 = _chunkS3QELJUEcjs.pulseBeats.call(void 0, ts);
|
|
796
|
+
return _chunkS3QELJUEcjs.isCompound.call(void 0, ts) ? pulse2 / 3 : pulse2 / 2;
|
|
774
797
|
}
|
|
775
798
|
function gridMetricWeight(step, ts) {
|
|
776
|
-
|
|
777
|
-
return stepWeight(step,
|
|
799
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, step, "step");
|
|
800
|
+
return stepWeight(step, _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, ts, "ts")));
|
|
778
801
|
}
|
|
779
802
|
function stepWeight(step, ts) {
|
|
780
803
|
const beats = step * STEP_BEATS;
|
|
781
|
-
const weight =
|
|
804
|
+
const weight = _chunkS3QELJUEcjs.metricWeight.call(void 0, beats, ts);
|
|
782
805
|
if (weight > 0) {
|
|
783
806
|
return weight + 1;
|
|
784
807
|
}
|
|
@@ -788,47 +811,58 @@ function stepWeight(step, ts) {
|
|
|
788
811
|
}
|
|
789
812
|
function thin(events, amount, ts) {
|
|
790
813
|
const figure = assertGridEvents(events);
|
|
791
|
-
|
|
792
|
-
|
|
814
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, amount, 0, 1, "thin amount");
|
|
815
|
+
return thinFigure(figure, amount, _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, ts, "ts")));
|
|
816
|
+
}
|
|
817
|
+
function thinFigure(figure, amount, ts) {
|
|
793
818
|
const floor = Math.min(4, Math.floor(amount * 5));
|
|
794
|
-
return figure.filter((event) => stepWeight(event.step,
|
|
819
|
+
return figure.filter((event) => stepWeight(event.step, ts) >= floor);
|
|
795
820
|
}
|
|
796
821
|
function double(events, spanSteps = BAR_STEPS) {
|
|
797
822
|
assertSpanSteps(spanSteps);
|
|
798
823
|
const sorted = [...assertGridEvents(events)].sort((a, b) => a.step - b.step);
|
|
799
|
-
const
|
|
800
|
-
|
|
824
|
+
const nextStep = [];
|
|
825
|
+
const following = /* @__PURE__ */ new Map();
|
|
826
|
+
for (let i = sorted.length - 1; i >= 0; i -= 1) {
|
|
801
827
|
const event = sorted[i];
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
828
|
+
const stream = streamOf(event);
|
|
829
|
+
nextStep[i] = _nullishCoalesce(following.get(stream), () => ( spanSteps));
|
|
830
|
+
following.set(stream, event.step);
|
|
831
|
+
}
|
|
832
|
+
const out = [];
|
|
833
|
+
sorted.forEach((event, i) => {
|
|
805
834
|
out.push(event);
|
|
806
|
-
const next = _nullishCoalesce(
|
|
835
|
+
const next = _nullishCoalesce(nextStep[i], () => ( spanSteps));
|
|
807
836
|
const mid = event.step + (next - event.step) / 2;
|
|
808
837
|
if (Number.isInteger(mid) && mid > event.step && mid < spanSteps) {
|
|
809
838
|
out.push({ ...event, step: mid, velocity: event.velocity * ADDED_NOTE_VELOCITY });
|
|
810
839
|
}
|
|
811
|
-
}
|
|
812
|
-
return out;
|
|
840
|
+
});
|
|
841
|
+
return out.sort((a, b) => a.step - b.step);
|
|
813
842
|
}
|
|
814
843
|
var ADDED_NOTE_VELOCITY = 0.75;
|
|
815
844
|
function halfTime(events, spanSteps = BAR_STEPS) {
|
|
816
845
|
assertSpanSteps(spanSteps);
|
|
817
|
-
return assertGridEvents(events)
|
|
846
|
+
return halfTimeFigure(assertGridEvents(events), spanSteps);
|
|
847
|
+
}
|
|
848
|
+
function halfTimeFigure(figure, spanSteps) {
|
|
849
|
+
return figure.map((event) => ({ ...event, step: event.step * 2 })).filter((event) => event.step < spanSteps);
|
|
818
850
|
}
|
|
819
851
|
function doubleTime(events, spanSteps = BAR_STEPS) {
|
|
820
852
|
assertSpanSteps(spanSteps);
|
|
821
|
-
assertGridEvents(events);
|
|
853
|
+
return doubleTimeFigure(assertGridEvents(events), spanSteps);
|
|
854
|
+
}
|
|
855
|
+
function doubleTimeFigure(figure, spanSteps) {
|
|
822
856
|
const merged = /* @__PURE__ */ new Map();
|
|
823
857
|
const place = (event, step, velocity) => {
|
|
824
|
-
const key =
|
|
858
|
+
const key = positionKey(event, step);
|
|
825
859
|
const held = merged.get(key);
|
|
826
860
|
if (held === void 0 || velocity > held.velocity) {
|
|
827
861
|
merged.set(key, { ...event, step, velocity });
|
|
828
862
|
}
|
|
829
863
|
};
|
|
830
|
-
for (const event of
|
|
831
|
-
const step =
|
|
864
|
+
for (const event of figure) {
|
|
865
|
+
const step = halvedStep(event.step);
|
|
832
866
|
place(event, step, event.velocity);
|
|
833
867
|
const repeated = step + spanSteps / 2;
|
|
834
868
|
if (repeated < spanSteps) {
|
|
@@ -841,18 +875,21 @@ function syncopate(events, amount, draw, ...path) {
|
|
|
841
875
|
const figure = assertGridEvents(events);
|
|
842
876
|
const sampler = assertDraw(draw);
|
|
843
877
|
assertSeedPath(path);
|
|
844
|
-
const asked = typeof amount === "number" ? void 0 :
|
|
878
|
+
const asked = typeof amount === "number" ? void 0 : _chunkS3QELJUEcjs.assertRecord.call(void 0, amount, "amount");
|
|
845
879
|
const dial = asked === void 0 ? amount : asked.amount;
|
|
846
|
-
const signature =
|
|
847
|
-
|
|
848
|
-
|
|
880
|
+
const signature = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(_optionalChain([asked, 'optionalAccess', _4 => _4.ts]), () => ( FIGURE_TS)), "ts"));
|
|
881
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, dial, 0, 1, "syncopate amount");
|
|
882
|
+
return syncopateFigure(figure, dial, signature, sampler, path);
|
|
883
|
+
}
|
|
884
|
+
function syncopateFigure(figure, dial, ts, sampler, path) {
|
|
885
|
+
const occupied = new Set(figure.map((event) => positionKey(event, event.step)));
|
|
849
886
|
const out = [...figure];
|
|
850
887
|
for (const event of figure) {
|
|
851
888
|
const anticipated = event.step - 1;
|
|
852
|
-
if (stepWeight(event.step,
|
|
889
|
+
if (stepWeight(event.step, ts) < 2 || anticipated < 1 || occupied.has(positionKey(event, anticipated))) {
|
|
853
890
|
continue;
|
|
854
891
|
}
|
|
855
|
-
if (!sampler.prob(dial, ...path, "syncopate", event
|
|
892
|
+
if (!sampler.prob(dial, ...path, "syncopate", ...drawKey(event))) {
|
|
856
893
|
continue;
|
|
857
894
|
}
|
|
858
895
|
out.push({ ...event, step: anticipated, velocity: event.velocity * ADDED_NOTE_VELOCITY });
|
|
@@ -861,39 +898,51 @@ function syncopate(events, amount, draw, ...path) {
|
|
|
861
898
|
}
|
|
862
899
|
function ornamentBy(events, isOrnament, amount, draw, ...path) {
|
|
863
900
|
const figure = assertGridEvents(events);
|
|
864
|
-
const marks =
|
|
901
|
+
const marks = _chunkS3QELJUEcjs.assertFunction.call(void 0, isOrnament, "isOrnament");
|
|
865
902
|
const sampler = assertDraw(draw);
|
|
866
903
|
assertSeedPath(path);
|
|
867
|
-
|
|
904
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, amount, 0, 1, "ornament amount");
|
|
905
|
+
return ornamentFigure(figure, marks, amount, sampler, path);
|
|
906
|
+
}
|
|
907
|
+
function ornamentFigure(figure, marks, amount, sampler, path) {
|
|
868
908
|
return figure.filter(
|
|
869
|
-
(event) => !marks(event) || sampler.prob(amount, ...path, "ornament", event
|
|
909
|
+
(event) => !marks(event) || sampler.prob(amount, ...path, "ornament", ...drawKey(event))
|
|
870
910
|
);
|
|
871
911
|
}
|
|
872
912
|
var NEUTRAL_RHYTHMIC = 0.5;
|
|
873
913
|
function deform(events, opts, draw, ...path) {
|
|
874
914
|
const figure = assertGridEvents(events);
|
|
875
|
-
const asked =
|
|
876
|
-
assertDraw(draw);
|
|
915
|
+
const asked = _chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "opts");
|
|
916
|
+
const sampler = assertDraw(draw);
|
|
877
917
|
assertSeedPath(path);
|
|
878
918
|
const spanSteps = assertSpanSteps(asked.spanSteps === void 0 ? BAR_STEPS : asked.spanSteps);
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
919
|
+
return deformFigure(figure, spanSteps, resolveDials(asked), sampler, path);
|
|
920
|
+
}
|
|
921
|
+
function resolveDials(asked) {
|
|
922
|
+
const rate = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(asked.rate, () => ( "straight")), FIGURE_RATES, "rate");
|
|
923
|
+
const rhythmic = asked.rhythmic === void 0 ? void 0 : _chunkS3QELJUEcjs.assertRange.call(void 0, asked.rhythmic, 0, 1, "complexity rhythmic");
|
|
924
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(asked.ts, () => ( FIGURE_TS)), "ts"));
|
|
925
|
+
const ornament2 = asked.ornament === void 0 ? void 0 : _chunkS3QELJUEcjs.assertRange.call(void 0, asked.ornament, 0, 1, "ornament amount");
|
|
926
|
+
const isOrnament = asked.isOrnament ? _chunkS3QELJUEcjs.assertFunction.call(void 0, asked.isOrnament, "opts.isOrnament") : void 0;
|
|
927
|
+
return { rate, rhythmic, ts, ornament: ornament2, isOrnament };
|
|
928
|
+
}
|
|
929
|
+
function deformFigure(figure, spanSteps, dials, sampler, path) {
|
|
930
|
+
let out = dials.rate === "half" ? halfTimeFigure(figure, spanSteps) : dials.rate === "double" ? doubleTimeFigure(figure, spanSteps) : [...figure];
|
|
931
|
+
const { rhythmic } = dials;
|
|
932
|
+
if (rhythmic !== void 0 && rhythmic < NEUTRAL_RHYTHMIC) {
|
|
933
|
+
out = thinFigure(out, (NEUTRAL_RHYTHMIC - rhythmic) / NEUTRAL_RHYTHMIC, dials.ts);
|
|
934
|
+
} else if (rhythmic !== void 0 && rhythmic > NEUTRAL_RHYTHMIC) {
|
|
935
|
+
out = syncopateFigure(
|
|
936
|
+
out,
|
|
937
|
+
(rhythmic - NEUTRAL_RHYTHMIC) / NEUTRAL_RHYTHMIC,
|
|
938
|
+
dials.ts,
|
|
939
|
+
sampler,
|
|
940
|
+
path
|
|
941
|
+
);
|
|
893
942
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
out =
|
|
943
|
+
const { ornament: ornament2, isOrnament } = dials;
|
|
944
|
+
if (ornament2 !== void 0 && isOrnament !== void 0) {
|
|
945
|
+
out = ornamentFigure(out, (event) => isOrnament(event), ornament2, sampler, path);
|
|
897
946
|
}
|
|
898
947
|
return out.sort((a, b) => a.step - b.step);
|
|
899
948
|
}
|
|
@@ -902,7 +951,7 @@ function withinCeiling(events, bpm, difficulty) {
|
|
|
902
951
|
if (difficulty === void 0 || bpm === void 0) {
|
|
903
952
|
return true;
|
|
904
953
|
}
|
|
905
|
-
|
|
954
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, bpm, "bpm");
|
|
906
955
|
assertDifficulty(difficulty);
|
|
907
956
|
if (figure.length < 2) {
|
|
908
957
|
return true;
|
|
@@ -940,8 +989,8 @@ function impliedScaleTones(chord) {
|
|
|
940
989
|
if (chordDegreeSemitone(7, chord) === void 0) {
|
|
941
990
|
return void 0;
|
|
942
991
|
}
|
|
943
|
-
for (const match of
|
|
944
|
-
const mask =
|
|
992
|
+
for (const match of _chunkP3CPXAJ5cjs.chordScales.call(void 0, chord)) {
|
|
993
|
+
const mask = _chunkYDGMWH43cjs.namedScaleMask.call(void 0, match.name);
|
|
945
994
|
if (mask === void 0) {
|
|
946
995
|
continue;
|
|
947
996
|
}
|
|
@@ -961,7 +1010,7 @@ function replacedDegreeSemitone(degree, chord) {
|
|
|
961
1010
|
if (degree !== 3) {
|
|
962
1011
|
return void 0;
|
|
963
1012
|
}
|
|
964
|
-
const sounds = (semitones) => chord.intervals.some((interval) =>
|
|
1013
|
+
const sounds = (semitones) => chord.intervals.some((interval) => _chunkS3QELJUEcjs.pitchClassOf.call(void 0, interval) === semitones);
|
|
965
1014
|
if (sounds(3) || sounds(4)) {
|
|
966
1015
|
return void 0;
|
|
967
1016
|
}
|
|
@@ -971,14 +1020,14 @@ function degreeSemitone(degree, alter, chord, key, implied) {
|
|
|
971
1020
|
const octaves = Math.floor((degree - 1) / 7);
|
|
972
1021
|
const within = (degree - 1) % 7 + 1;
|
|
973
1022
|
const template = _nullishCoalesce(MAJOR_DEGREE_SEMITONES[within - 1], () => ( 0));
|
|
974
|
-
const semitone = alter !== 0 ? template : _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(chordDegreeSemitone(within, chord), () => ( replacedDegreeSemitone(within, chord))), () => ( _optionalChain([implied, 'optionalAccess',
|
|
1023
|
+
const semitone = alter !== 0 ? template : _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(chordDegreeSemitone(within, chord), () => ( replacedDegreeSemitone(within, chord))), () => ( _optionalChain([implied, 'optionalAccess', _5 => _5[within - 1]]))), () => ( // A degree neither the chord nor its quality settles is a passing tone,
|
|
975
1024
|
// so the key decides it.
|
|
976
|
-
|
|
977
|
-
return
|
|
1025
|
+
_chunkYDGMWH43cjs.nearestScaleTone.call(void 0, chord.rootPc + template, key) - chord.rootPc));
|
|
1026
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, semitone) + 12 * octaves + alter;
|
|
978
1027
|
}
|
|
979
1028
|
function chordDegreeSemitone(degree, chord) {
|
|
980
1029
|
for (const interval of chord.intervals) {
|
|
981
|
-
if (
|
|
1030
|
+
if (_chunkYDGMWH43cjs.degreeOfInterval.call(void 0, interval, chord) === degree) {
|
|
982
1031
|
return interval;
|
|
983
1032
|
}
|
|
984
1033
|
}
|
|
@@ -1010,6 +1059,32 @@ function isLickMaterial(material) {
|
|
|
1010
1059
|
const candidate = material;
|
|
1011
1060
|
return typeof candidate === "object" && candidate !== null && typeof candidate.lengthSteps === "number" && Array.isArray(candidate.notes);
|
|
1012
1061
|
}
|
|
1062
|
+
function assertLickMaterial(material, label) {
|
|
1063
|
+
material.notes.forEach((given, index) => {
|
|
1064
|
+
const name = `${label} notes[${index}]`;
|
|
1065
|
+
const lickNote = _chunkS3QELJUEcjs.assertRecord.call(void 0, given, name);
|
|
1066
|
+
_chunkS3QELJUEcjs.assertDegree.call(void 0, lickNote.degree, `${name}.degree`);
|
|
1067
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, lickNote.step, `${name}.step`);
|
|
1068
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, lickNote.velocity, `${name}.velocity`);
|
|
1069
|
+
if (lickNote.alter !== void 0) {
|
|
1070
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, lickNote.alter, `${name}.alter`);
|
|
1071
|
+
}
|
|
1072
|
+
if (lickNote.lengthSteps !== void 0) {
|
|
1073
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, lickNote.lengthSteps, `${name}.lengthSteps`);
|
|
1074
|
+
}
|
|
1075
|
+
if (lickNote.articulation !== void 0) {
|
|
1076
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, lickNote.articulation, _chunkS3QELJUEcjs.ARTICULATIONS, `${name}.articulation`);
|
|
1077
|
+
}
|
|
1078
|
+
for (const field of ["voice", "limb"]) {
|
|
1079
|
+
const value = lickNote[field];
|
|
1080
|
+
if (value !== void 0 && typeof value !== "string") {
|
|
1081
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
1082
|
+
`${name}.${field} must be a string; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, value)}`
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1013
1088
|
function note(degree, step, velocity, extra) {
|
|
1014
1089
|
return { degree, step, velocity, ...extra };
|
|
1015
1090
|
}
|
|
@@ -1208,28 +1283,28 @@ var BASS_LICKS = deepFreeze([
|
|
|
1208
1283
|
var DEFAULT_BPM = 120;
|
|
1209
1284
|
var DEFAULT_LICK_DENSITY = 0.6;
|
|
1210
1285
|
function placeLicks(timeline, key, opts) {
|
|
1211
|
-
const asked =
|
|
1212
|
-
const placement =
|
|
1286
|
+
const asked = _chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "opts");
|
|
1287
|
+
const placement = _chunkS3QELJUEcjs.assertArray.call(void 0,
|
|
1213
1288
|
timeline,
|
|
1214
1289
|
"timeline"
|
|
1215
1290
|
);
|
|
1216
|
-
|
|
1217
|
-
const genre =
|
|
1218
|
-
const ts =
|
|
1291
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, placement.length, "lick segments", asked.budget);
|
|
1292
|
+
const genre = _chunkS3QELJUEcjs.assertOneOf.call(void 0, asked.genre, GENRES, "lick genre");
|
|
1293
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(asked.ts, () => ( DEFAULT_TS)), "ts"));
|
|
1219
1294
|
const octave = _nullishCoalesce(asked.octave, () => ( DEFAULT_OCTAVE));
|
|
1220
|
-
|
|
1221
|
-
const scale =
|
|
1222
|
-
const segments = placement.map((segment) => ({ ...segment, chord:
|
|
1295
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, octave, "lick octave", -1, 8);
|
|
1296
|
+
const scale = _chunkYDGMWH43cjs.toKeyScale.call(void 0, key);
|
|
1297
|
+
const segments = placement.map((segment) => ({ ...segment, chord: _chunkYDGMWH43cjs.toChordData.call(void 0, segment.chord) })).sort((a, b) => a.startBeat - b.startBeat);
|
|
1223
1298
|
assertBassSegments(segments);
|
|
1224
1299
|
if (segments.length === 0) {
|
|
1225
1300
|
return [];
|
|
1226
1301
|
}
|
|
1227
|
-
const barBeats =
|
|
1302
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts);
|
|
1228
1303
|
const estimatedBars = segments.reduce(
|
|
1229
1304
|
(count, segment) => count + Math.max(1, Math.ceil((segment.endBeat - segment.startBeat) / barBeats)),
|
|
1230
1305
|
0
|
|
1231
1306
|
);
|
|
1232
|
-
|
|
1307
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, estimatedBars, "lick bars", asked.budget);
|
|
1233
1308
|
const resolved = resolveContext(asked.ctx);
|
|
1234
1309
|
const draw = resolved.part("bass");
|
|
1235
1310
|
const bpm = _nullishCoalesce(resolved.bpm, () => ( DEFAULT_BPM));
|
|
@@ -1237,10 +1312,11 @@ function placeLicks(timeline, key, opts) {
|
|
|
1237
1312
|
const supplied = asked.difficulty === void 0 ? void 0 : assertDifficulty(asked.difficulty, "lick difficulty");
|
|
1238
1313
|
const difficulty = _nullishCoalesce(resolved.difficulty, () => ( supplied));
|
|
1239
1314
|
const { instrument, low } = bassRegister(resolved.instrument("bass"), asked.instrument, octave);
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
);
|
|
1315
|
+
const callerLicks = vocabularyOfKind(resolved.vocabulary, isLickMaterial);
|
|
1316
|
+
callerLicks.forEach((entry, index) => {
|
|
1317
|
+
assertLickMaterial(entry.material, `lick vocabulary[${index}]`);
|
|
1318
|
+
});
|
|
1319
|
+
const dictionary = mergeVocabulary(BASS_LICKS, callerLicks);
|
|
1244
1320
|
const playable = instrument === void 0 ? {} : { articulations: instrument.articulations };
|
|
1245
1321
|
const raw = [];
|
|
1246
1322
|
for (let index = 0; index < segments.length; index += 1) {
|
|
@@ -1256,7 +1332,7 @@ function placeLicks(timeline, key, opts) {
|
|
|
1256
1332
|
let firstOnset = segment.startBeat;
|
|
1257
1333
|
const tiles = barTiles(segment.startBeat, segment.endBeat, ts);
|
|
1258
1334
|
for (let tile = 0; tile < tiles.length; tile += 1) {
|
|
1259
|
-
const tileStart = _nullishCoalesce(_optionalChain([tiles, 'access',
|
|
1335
|
+
const tileStart = _nullishCoalesce(_optionalChain([tiles, 'access', _6 => _6[tile], 'optionalAccess', _7 => _7.startBeat]), () => ( segment.startBeat));
|
|
1260
1336
|
const remaining = segment.endBeat - tileStart;
|
|
1261
1337
|
const entry = pickVocabulary(
|
|
1262
1338
|
dictionary,
|
|
@@ -1289,7 +1365,7 @@ function placeLicks(timeline, key, opts) {
|
|
|
1289
1365
|
}
|
|
1290
1366
|
raw.push({ startBeat: rootAt, pitch: rootMidi, velocity: STRONG_VELOCITY });
|
|
1291
1367
|
if (notes) {
|
|
1292
|
-
const figureRoot = segment.chord.bassPc === void 0 ? placePc(
|
|
1368
|
+
const figureRoot = segment.chord.bassPc === void 0 ? placePc(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, segment.chord.rootPc), rootMidi, low) : placeAboveBass(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, segment.chord.rootPc), rootMidi);
|
|
1293
1369
|
for (const lickNote of notes) {
|
|
1294
1370
|
const at2 = tileStart + lickNote.step * STEP_BEATS;
|
|
1295
1371
|
const offset = degreeSemitone(
|
|
@@ -1299,12 +1375,12 @@ function placeLicks(timeline, key, opts) {
|
|
|
1299
1375
|
scale,
|
|
1300
1376
|
implied
|
|
1301
1377
|
);
|
|
1302
|
-
const pitch = Math.abs(at2 - rootAt) <
|
|
1378
|
+
const pitch = Math.abs(at2 - rootAt) < _chunkS3QELJUEcjs.BEAT_EPS && lickNote.degree === 1 && (_nullishCoalesce(lickNote.alter, () => ( 0))) === 0 ? rootMidi : figureRoot + offset;
|
|
1303
1379
|
raw.push({
|
|
1304
1380
|
startBeat: at2,
|
|
1305
1381
|
pitch,
|
|
1306
1382
|
velocity: Math.round(
|
|
1307
|
-
(
|
|
1383
|
+
(_chunkS3QELJUEcjs.isStrongBeat.call(void 0, at2, ts) ? STRONG_VELOCITY : WEAK_VELOCITY) * lickNote.velocity
|
|
1308
1384
|
),
|
|
1309
1385
|
note: lickNote
|
|
1310
1386
|
});
|
|
@@ -1315,7 +1391,7 @@ function placeLicks(timeline, key, opts) {
|
|
|
1315
1391
|
if (next && lastTilePlayed) {
|
|
1316
1392
|
const lastBeat = next.startBeat - STEP_BEATS * BEAT_STEPS;
|
|
1317
1393
|
const approachAt = _nullishCoalesce(materialOnsetIn(playedTile, lastBeat, next.startBeat), () => ( lastBeat));
|
|
1318
|
-
if (approachAt > firstOnset +
|
|
1394
|
+
if (approachAt > firstOnset + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1319
1395
|
const nextRoot = placeRoot(bassPcOf(next.chord), low);
|
|
1320
1396
|
const occupied = soundingAt(raw, approachAt);
|
|
1321
1397
|
const distance = occupied === void 0 ? 0 : Math.abs(occupied.pitch - nextRoot);
|
|
@@ -1339,23 +1415,23 @@ function placeLicks(timeline, key, opts) {
|
|
|
1339
1415
|
if (!item) {
|
|
1340
1416
|
continue;
|
|
1341
1417
|
}
|
|
1342
|
-
const nextStart = _nullishCoalesce(_optionalChain([raw, 'access',
|
|
1343
|
-
const written = _optionalChain([item, 'access',
|
|
1418
|
+
const nextStart = _nullishCoalesce(_optionalChain([raw, 'access', _8 => _8[i + 1], 'optionalAccess', _9 => _9.startBeat]), () => ( lastEnd));
|
|
1419
|
+
const written = _optionalChain([item, 'access', _10 => _10.note, 'optionalAccess', _11 => _11.lengthSteps]);
|
|
1344
1420
|
const durationBeat = Math.min(
|
|
1345
1421
|
nextStart - item.startBeat,
|
|
1346
1422
|
written === void 0 ? Number.POSITIVE_INFINITY : written * STEP_BEATS
|
|
1347
1423
|
);
|
|
1348
|
-
if (durationBeat <=
|
|
1424
|
+
if (durationBeat <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1349
1425
|
continue;
|
|
1350
1426
|
}
|
|
1351
|
-
const placed = instrument ?
|
|
1427
|
+
const placed = instrument ? _chunkWOMCXN2Wcjs.foldIntoRange.call(void 0, item.pitch, instrument) : item.pitch;
|
|
1352
1428
|
const event = {
|
|
1353
|
-
pitch:
|
|
1429
|
+
pitch: _chunkS3QELJUEcjs.clampToMidi.call(void 0, placed, "generated bass pitch"),
|
|
1354
1430
|
startBeat: item.startBeat,
|
|
1355
1431
|
durationBeat,
|
|
1356
1432
|
velocity: Math.max(1, Math.min(127, item.velocity))
|
|
1357
1433
|
};
|
|
1358
|
-
if (_optionalChain([item, 'access',
|
|
1434
|
+
if (_optionalChain([item, 'access', _12 => _12.note, 'optionalAccess', _13 => _13.articulation])) {
|
|
1359
1435
|
event.articulation = item.note.articulation;
|
|
1360
1436
|
}
|
|
1361
1437
|
out.push(event);
|
|
@@ -1365,7 +1441,7 @@ function placeLicks(timeline, key, opts) {
|
|
|
1365
1441
|
function soundingAt(raw, at2) {
|
|
1366
1442
|
for (let index = raw.length - 1; index >= 0; index -= 1) {
|
|
1367
1443
|
const item = raw[index];
|
|
1368
|
-
if (item !== void 0 && Math.abs(item.startBeat - at2) <
|
|
1444
|
+
if (item !== void 0 && Math.abs(item.startBeat - at2) < _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1369
1445
|
return item;
|
|
1370
1446
|
}
|
|
1371
1447
|
}
|
|
@@ -1378,7 +1454,7 @@ function materialOnsetIn(played, from, to) {
|
|
|
1378
1454
|
let last;
|
|
1379
1455
|
for (const note2 of played.material.notes) {
|
|
1380
1456
|
const at2 = played.tileStart + note2.step * STEP_BEATS;
|
|
1381
|
-
if (at2 < from -
|
|
1457
|
+
if (at2 < from - _chunkS3QELJUEcjs.BEAT_EPS || at2 > to - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1382
1458
|
continue;
|
|
1383
1459
|
}
|
|
1384
1460
|
last = last === void 0 ? at2 : Math.max(last, at2);
|
|
@@ -1388,7 +1464,7 @@ function materialOnsetIn(played, from, to) {
|
|
|
1388
1464
|
function lastPitchBefore(raw, at2, fallback) {
|
|
1389
1465
|
for (let index = raw.length - 1; index >= 0; index -= 1) {
|
|
1390
1466
|
const item = raw[index];
|
|
1391
|
-
if (item !== void 0 && item.startBeat < at2 -
|
|
1467
|
+
if (item !== void 0 && item.startBeat < at2 - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1392
1468
|
return item.pitch;
|
|
1393
1469
|
}
|
|
1394
1470
|
}
|
|
@@ -1401,7 +1477,7 @@ function anchorStepOf(material, spanBeats) {
|
|
|
1401
1477
|
first = note2.step;
|
|
1402
1478
|
}
|
|
1403
1479
|
}
|
|
1404
|
-
if (first === void 0 || first < 0 || first * STEP_BEATS >= spanBeats -
|
|
1480
|
+
if (first === void 0 || first < 0 || first * STEP_BEATS >= spanBeats - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1405
1481
|
return 0;
|
|
1406
1482
|
}
|
|
1407
1483
|
return first;
|
|
@@ -1428,7 +1504,7 @@ function fitToSegment(material, spanBeats, density, resolved, draw, path, bpm, d
|
|
|
1428
1504
|
...path
|
|
1429
1505
|
);
|
|
1430
1506
|
const spanSteps = spanBeats / STEP_BEATS;
|
|
1431
|
-
const inside = deformed.filter((lickNote) => lickNote.step < spanSteps -
|
|
1507
|
+
const inside = deformed.filter((lickNote) => lickNote.step < spanSteps - _chunkS3QELJUEcjs.BEAT_EPS);
|
|
1432
1508
|
if (inside.length === 0 || !withinCeiling(inside, bpm, difficulty)) {
|
|
1433
1509
|
return void 0;
|
|
1434
1510
|
}
|
|
@@ -1446,15 +1522,15 @@ var BASS_STYLES = Object.freeze([
|
|
|
1446
1522
|
var DEFAULT_STYLE = "root";
|
|
1447
1523
|
var DEFAULT_PICKUP_DENSITY = 0.35;
|
|
1448
1524
|
function sounding(ctx, placed) {
|
|
1449
|
-
return ctx.instrument ?
|
|
1525
|
+
return ctx.instrument ? _chunkWOMCXN2Wcjs.foldIntoRange.call(void 0, placed, ctx.instrument) : placed;
|
|
1450
1526
|
}
|
|
1451
1527
|
function placeTone(ctx, pc) {
|
|
1452
1528
|
return ctx.overBass ? placeAboveBass(pc, ctx.rootMidi) : placePc(pc, ctx.rootMidi, ctx.low);
|
|
1453
1529
|
}
|
|
1454
1530
|
function emit(ctx, pos, pc, midiOverride) {
|
|
1455
|
-
const placed =
|
|
1531
|
+
const placed = _chunkS3QELJUEcjs.clampToMidi.call(void 0, _nullishCoalesce(midiOverride, () => ( placeTone(ctx, pc))), "generated bass pitch");
|
|
1456
1532
|
const midi = sounding(ctx, placed);
|
|
1457
|
-
const velocity =
|
|
1533
|
+
const velocity = _chunkS3QELJUEcjs.isStrongBeat.call(void 0, pos, ctx.ts) ? STRONG_VELOCITY : WEAK_VELOCITY;
|
|
1458
1534
|
ctx.notes.push({ startBeat: pos, pitch: midi, velocity });
|
|
1459
1535
|
ctx.prevMidi = midi;
|
|
1460
1536
|
return midi;
|
|
@@ -1466,7 +1542,7 @@ function buildRootFifth(ctx, seg) {
|
|
|
1466
1542
|
for (const tile of barTiles(seg.startBeat, seg.endBeat, ctx.ts)) {
|
|
1467
1543
|
emit(ctx, tile.startBeat, bassPcOf(seg.chord));
|
|
1468
1544
|
const answer = midBarPulse(tile.startBeat, ctx.ts);
|
|
1469
|
-
if (answer > tile.startBeat +
|
|
1545
|
+
if (answer > tile.startBeat + _chunkS3QELJUEcjs.BEAT_EPS && answer < tile.endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1470
1546
|
emit(ctx, answer, fifthPcOf2(seg.chord));
|
|
1471
1547
|
}
|
|
1472
1548
|
}
|
|
@@ -1476,7 +1552,7 @@ function buildPop(ctx, seg, index) {
|
|
|
1476
1552
|
const rootPc = bassPcOf(seg.chord);
|
|
1477
1553
|
let emitted = false;
|
|
1478
1554
|
for (const pos of positions) {
|
|
1479
|
-
if (
|
|
1555
|
+
if (_chunkS3QELJUEcjs.isStrongBeat.call(void 0, pos, ctx.ts)) {
|
|
1480
1556
|
emit(ctx, pos, rootPc);
|
|
1481
1557
|
emitted = true;
|
|
1482
1558
|
} else if (ctx.draw.prob(ctx.pickupDensity, "pickup", index, pos)) {
|
|
@@ -1537,7 +1613,7 @@ function buildWalking(ctx, seg, next, index) {
|
|
|
1537
1613
|
if (next && count > 1 && i === count - 1) {
|
|
1538
1614
|
const nextBass = placeRoot(bassPcOf(next.chord), ctx.low);
|
|
1539
1615
|
const midi = approachNote2(ctx, nextBass, ctx.prevMidi, index);
|
|
1540
|
-
emit(ctx, pos,
|
|
1616
|
+
emit(ctx, pos, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, midi), midi);
|
|
1541
1617
|
return;
|
|
1542
1618
|
}
|
|
1543
1619
|
const pc = _nullishCoalesce(tones[i % tones.length], () => ( bassPcOf(seg.chord)));
|
|
@@ -1545,29 +1621,29 @@ function buildWalking(ctx, seg, next, index) {
|
|
|
1545
1621
|
});
|
|
1546
1622
|
}
|
|
1547
1623
|
function generateBassLine(opts) {
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
const segments = opts.segments.map((segment) => ({ ...segment, chord:
|
|
1624
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "bass line options");
|
|
1625
|
+
_chunkS3QELJUEcjs.assertArray.call(void 0, opts.segments, "bass segments");
|
|
1626
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, opts.segments.length, "bass segments", opts.budget);
|
|
1627
|
+
const segments = opts.segments.map((segment) => ({ ...segment, chord: _chunkYDGMWH43cjs.toChordData.call(void 0, segment.chord) })).sort((a, b) => a.startBeat - b.startBeat);
|
|
1552
1628
|
assertBassSegments(segments);
|
|
1553
1629
|
if (segments.length === 0) {
|
|
1554
1630
|
return [];
|
|
1555
1631
|
}
|
|
1556
|
-
const ts =
|
|
1557
|
-
const style =
|
|
1632
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_TS)), "ts"));
|
|
1633
|
+
const style = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.style, () => ( DEFAULT_STYLE)), BASS_STYLES, "bass style");
|
|
1558
1634
|
const octave = _nullishCoalesce(opts.octave, () => ( DEFAULT_OCTAVE));
|
|
1559
|
-
|
|
1635
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, octave, "bass octave", -1, 8);
|
|
1560
1636
|
const estimatedNotes = segments.reduce(
|
|
1561
1637
|
(count, segment) => count + Math.max(1, Math.ceil(segment.endBeat - segment.startBeat)),
|
|
1562
1638
|
0
|
|
1563
1639
|
);
|
|
1564
|
-
|
|
1640
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, estimatedNotes, "bass notes", opts.budget);
|
|
1565
1641
|
const resolved = resolveContext(opts.ctx);
|
|
1566
1642
|
const { instrument, low } = bassRegister(resolved.instrument("bass"), opts.instrument, octave);
|
|
1567
1643
|
const ctx = {
|
|
1568
1644
|
ts,
|
|
1569
1645
|
low,
|
|
1570
|
-
key:
|
|
1646
|
+
key: _chunkYDGMWH43cjs.toKeyScale.call(void 0, opts.key),
|
|
1571
1647
|
draw: resolved.part("bass"),
|
|
1572
1648
|
notes: [],
|
|
1573
1649
|
rootMidi: low,
|
|
@@ -1611,13 +1687,13 @@ function generateBassLine(opts) {
|
|
|
1611
1687
|
if (!note2) {
|
|
1612
1688
|
continue;
|
|
1613
1689
|
}
|
|
1614
|
-
const nextStart = _nullishCoalesce(_optionalChain([ctx, 'access',
|
|
1690
|
+
const nextStart = _nullishCoalesce(_optionalChain([ctx, 'access', _14 => _14.notes, 'access', _15 => _15[i + 1], 'optionalAccess', _16 => _16.startBeat]), () => ( lastEnd));
|
|
1615
1691
|
const durationBeat = nextStart - note2.startBeat;
|
|
1616
|
-
if (durationBeat <=
|
|
1692
|
+
if (durationBeat <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1617
1693
|
continue;
|
|
1618
1694
|
}
|
|
1619
1695
|
out.push({
|
|
1620
|
-
pitch:
|
|
1696
|
+
pitch: _chunkS3QELJUEcjs.clampToMidi.call(void 0, note2.pitch, "generated bass pitch"),
|
|
1621
1697
|
startBeat: note2.startBeat,
|
|
1622
1698
|
durationBeat,
|
|
1623
1699
|
velocity: note2.velocity
|
|
@@ -1634,33 +1710,33 @@ function degreesOf(interval) {
|
|
|
1634
1710
|
}
|
|
1635
1711
|
function assertPlayable(pitch) {
|
|
1636
1712
|
if (pitch < 0 || pitch > 127) {
|
|
1637
|
-
throw new (0,
|
|
1713
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`imitated pitch ${pitch} is outside the MIDI range 0..127`);
|
|
1638
1714
|
}
|
|
1639
1715
|
return pitch;
|
|
1640
1716
|
}
|
|
1641
1717
|
function imitate(lead, opts) {
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
const interval =
|
|
1646
|
-
const key =
|
|
1718
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, lead, "imitate lead", { allowNonPositiveDuration: true });
|
|
1719
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "opts");
|
|
1720
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, opts.atBeat, "atBeat");
|
|
1721
|
+
const interval = _chunkS3QELJUEcjs.toSpelledInterval.call(void 0, opts.interval);
|
|
1722
|
+
const key = _chunkYDGMWH43cjs.toKeyScale.call(void 0, opts.key);
|
|
1647
1723
|
const from = _nullishCoalesce(opts.from, () => ( Number.NEGATIVE_INFINITY));
|
|
1648
1724
|
const to = _nullishCoalesce(opts.to, () => ( Number.POSITIVE_INFINITY));
|
|
1649
1725
|
if (opts.from !== void 0) {
|
|
1650
|
-
|
|
1726
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, opts.from, "from");
|
|
1651
1727
|
}
|
|
1652
1728
|
if (opts.to !== void 0) {
|
|
1653
|
-
|
|
1729
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, opts.to, "to");
|
|
1654
1730
|
}
|
|
1655
1731
|
if (from > to) {
|
|
1656
|
-
throw new (0,
|
|
1732
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`imitate needs from <= to; received ${from} > ${to}`);
|
|
1657
1733
|
}
|
|
1658
1734
|
const velocityScale = _nullishCoalesce(opts.velocityScale, () => ( 1));
|
|
1659
|
-
|
|
1660
|
-
const tonal =
|
|
1661
|
-
const subject =
|
|
1662
|
-
const origin = _optionalChain([subject, 'access',
|
|
1663
|
-
const pivot = _optionalChain([subject, 'access',
|
|
1735
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, velocityScale, "velocityScale");
|
|
1736
|
+
const tonal = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.answer, () => ( "real")), IMITATION_ANSWERS, "imitate answer") === "tonal";
|
|
1737
|
+
const subject = _chunkS3QELJUEcjs.dropSilentNotes.call(void 0, lead).filter((note2) => note2.startBeat >= from && note2.startBeat < to).sort((a, b) => a.startBeat - b.startBeat);
|
|
1738
|
+
const origin = _optionalChain([subject, 'access', _17 => _17[0], 'optionalAccess', _18 => _18.startBeat]);
|
|
1739
|
+
const pivot = _optionalChain([subject, 'access', _19 => _19[0], 'optionalAccess', _20 => _20.pitch]);
|
|
1664
1740
|
if (origin === void 0 || pivot === void 0) {
|
|
1665
1741
|
return [];
|
|
1666
1742
|
}
|
|
@@ -1672,14 +1748,15 @@ function imitate(lead, opts) {
|
|
|
1672
1748
|
let offset = 0;
|
|
1673
1749
|
if (invert) {
|
|
1674
1750
|
if (tonal) {
|
|
1675
|
-
const
|
|
1676
|
-
|
|
1677
|
-
|
|
1751
|
+
const axis = _chunkYDGMWH43cjs.scaleLadderPosition.call(void 0, pivot, key);
|
|
1752
|
+
const here = _chunkYDGMWH43cjs.scaleLadderPosition.call(void 0, pitch - axis.offset, key);
|
|
1753
|
+
pitch = _chunkYDGMWH43cjs.scaleLadderPitch.call(void 0, 2 * axis.rung - here.rung, key);
|
|
1754
|
+
offset = axis.offset - here.offset;
|
|
1678
1755
|
} else {
|
|
1679
1756
|
pitch = 2 * pivot - pitch;
|
|
1680
1757
|
}
|
|
1681
1758
|
}
|
|
1682
|
-
pitch = tonal ?
|
|
1759
|
+
pitch = tonal ? _chunkYDGMWH43cjs.shiftByScaleDegrees.call(void 0, pitch, degrees, key) + offset : pitch + Math.round(interval.semitones);
|
|
1683
1760
|
const answer = {
|
|
1684
1761
|
...note2,
|
|
1685
1762
|
pitch: assertPlayable(pitch),
|
|
@@ -1704,10 +1781,10 @@ var DEFAULT_MELODY_VELOCITY = 96;
|
|
|
1704
1781
|
var VELOCITY_DROP = 16;
|
|
1705
1782
|
var TIE_BREAK_JITTER = 1e-6;
|
|
1706
1783
|
function isWholeBeat(beat) {
|
|
1707
|
-
return Math.abs(beat - Math.round(beat)) <
|
|
1784
|
+
return Math.abs(beat - Math.round(beat)) < _chunkS3QELJUEcjs.BEAT_EPS;
|
|
1708
1785
|
}
|
|
1709
1786
|
function melodyNoteAt(melody, beat) {
|
|
1710
|
-
return _optionalChain([melody, 'access',
|
|
1787
|
+
return _optionalChain([melody, 'access', _21 => _21.at, 'call', _22 => _22(beat), 'optionalAccess', _23 => _23.note]);
|
|
1711
1788
|
}
|
|
1712
1789
|
function melodyAttacksAt(melody, beat) {
|
|
1713
1790
|
return melody.attacksAt(beat);
|
|
@@ -1717,8 +1794,8 @@ function melodySnapshotAt(melody, beat) {
|
|
|
1717
1794
|
if (current === void 0) {
|
|
1718
1795
|
return void 0;
|
|
1719
1796
|
}
|
|
1720
|
-
const attacked = Math.abs(current.startBeat - beat) <
|
|
1721
|
-
const previous = attacked ? melodyNoteAt(melody, beat -
|
|
1797
|
+
const attacked = Math.abs(current.startBeat - beat) < _chunkS3QELJUEcjs.BEAT_EPS;
|
|
1798
|
+
const previous = attacked ? melodyNoteAt(melody, beat - _chunkS3QELJUEcjs.BEAT_EPS * 2) : current;
|
|
1722
1799
|
const snapshot = { pitch: current.pitch };
|
|
1723
1800
|
if (previous !== void 0) {
|
|
1724
1801
|
snapshot.prevPitch = previous.pitch;
|
|
@@ -1734,7 +1811,7 @@ function complementOnsets(melody, ts, spanStart, spanEnd, draw) {
|
|
|
1734
1811
|
const onsets = [];
|
|
1735
1812
|
const gridStart = Math.floor(spanStart / GRID_STEP) * GRID_STEP;
|
|
1736
1813
|
let last = Number.NEGATIVE_INFINITY;
|
|
1737
|
-
for (let beat = gridStart; beat < spanEnd -
|
|
1814
|
+
for (let beat = gridStart; beat < spanEnd - _chunkS3QELJUEcjs.BEAT_EPS; beat += GRID_STEP) {
|
|
1738
1815
|
const attacked = melodyAttacksAt(melody, beat);
|
|
1739
1816
|
const sounding2 = melodyNoteAt(melody, beat) !== void 0;
|
|
1740
1817
|
let place = false;
|
|
@@ -1742,10 +1819,10 @@ function complementOnsets(melody, ts, spanStart, spanEnd, draw) {
|
|
|
1742
1819
|
place = isWholeBeat(beat);
|
|
1743
1820
|
} else if (!attacked) {
|
|
1744
1821
|
place = draw.prob(isWholeBeat(beat) ? HOLD_ON_BEAT_PROB : HOLD_OFF_BEAT_PROB, "hold", beat);
|
|
1745
|
-
} else if (
|
|
1822
|
+
} else if (_chunkS3QELJUEcjs.isStrongBeat.call(void 0, beat, ts)) {
|
|
1746
1823
|
place = draw.prob(REINFORCE_PROB, "reinforce", beat);
|
|
1747
1824
|
}
|
|
1748
|
-
if (place && beat - last >= MIN_ONSET_GAP -
|
|
1825
|
+
if (place && beat - last >= MIN_ONSET_GAP - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1749
1826
|
onsets.push(beat);
|
|
1750
1827
|
last = beat;
|
|
1751
1828
|
}
|
|
@@ -1766,12 +1843,12 @@ function assertWeightOverrides(overrides) {
|
|
|
1766
1843
|
return;
|
|
1767
1844
|
}
|
|
1768
1845
|
if (typeof overrides !== "object" || overrides === null) {
|
|
1769
|
-
throw new (0,
|
|
1770
|
-
`countermelody weights must be an object of weight overrides; received ${
|
|
1846
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
1847
|
+
`countermelody weights must be an object of weight overrides; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, overrides)}`
|
|
1771
1848
|
);
|
|
1772
1849
|
}
|
|
1773
1850
|
for (const [field, value] of Object.entries(overrides)) {
|
|
1774
|
-
|
|
1851
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, value, `countermelody weights.${field}`);
|
|
1775
1852
|
}
|
|
1776
1853
|
}
|
|
1777
1854
|
function scoreCandidate(pitch, melPitch, melPrev, prevPitch, chord, center, weights) {
|
|
@@ -1786,7 +1863,7 @@ function scoreCandidate(pitch, melPitch, melPrev, prevPitch, chord, center, weig
|
|
|
1786
1863
|
score += weights.dissonance;
|
|
1787
1864
|
}
|
|
1788
1865
|
}
|
|
1789
|
-
if (chord &&
|
|
1866
|
+
if (chord && _chunkYDGMWH43cjs.chordToneRole.call(void 0, pitch, chord) !== null) {
|
|
1790
1867
|
score += weights.chordTone;
|
|
1791
1868
|
}
|
|
1792
1869
|
if (prevPitch !== void 0) {
|
|
@@ -1796,7 +1873,7 @@ function scoreCandidate(pitch, melPitch, melPrev, prevPitch, chord, center, weig
|
|
|
1796
1873
|
if (dist > 0 && dist <= 2) {
|
|
1797
1874
|
score += weights.stepwise;
|
|
1798
1875
|
}
|
|
1799
|
-
if (
|
|
1876
|
+
if (_chunkYDGMWH43cjs.isForbiddenMelodicLeap.call(void 0, prevPitch, pitch)) {
|
|
1800
1877
|
score += weights.forbiddenLeap;
|
|
1801
1878
|
}
|
|
1802
1879
|
if (melPitch !== void 0 && melPrev !== void 0 && ic !== void 0) {
|
|
@@ -1821,12 +1898,12 @@ function heldNoteBoundaries(melody, startBeat, endBeat, chordChangeBeats) {
|
|
|
1821
1898
|
boundaries.add(onset);
|
|
1822
1899
|
}
|
|
1823
1900
|
for (const beat of chordChangeBeats) {
|
|
1824
|
-
if (beat > startBeat +
|
|
1901
|
+
if (beat > startBeat + _chunkS3QELJUEcjs.BEAT_EPS && beat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
1825
1902
|
boundaries.add(beat);
|
|
1826
1903
|
}
|
|
1827
1904
|
}
|
|
1828
1905
|
const firstGrid = Math.floor(startBeat / GRID_STEP + 1) * GRID_STEP;
|
|
1829
|
-
for (let beat = firstGrid; beat < endBeat -
|
|
1906
|
+
for (let beat = firstGrid; beat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS; beat += GRID_STEP) {
|
|
1830
1907
|
boundaries.add(beat);
|
|
1831
1908
|
}
|
|
1832
1909
|
return [...boundaries].sort((a, b) => a - b);
|
|
@@ -1839,8 +1916,8 @@ function boundaryContexts(melody, harmony, startBeat, endBeat, ts) {
|
|
|
1839
1916
|
melodyVoice,
|
|
1840
1917
|
otherVoices: melodyVoice === void 0 ? [] : [melodyVoice],
|
|
1841
1918
|
chord: harmony.chordAt(boundary),
|
|
1842
|
-
strongBeat:
|
|
1843
|
-
atCounterOnset: Math.abs(boundary - startBeat) <
|
|
1919
|
+
strongBeat: _chunkS3QELJUEcjs.isStrongBeat.call(void 0, boundary, ts),
|
|
1920
|
+
atCounterOnset: Math.abs(boundary - startBeat) < _chunkS3QELJUEcjs.BEAT_EPS
|
|
1844
1921
|
};
|
|
1845
1922
|
});
|
|
1846
1923
|
}
|
|
@@ -1851,7 +1928,7 @@ function heldPitchSafety(pitch, contexts, prevPitch, key, profile, register, low
|
|
|
1851
1928
|
if (melodyVoice !== void 0 && (register === "below" && pitch >= melodyVoice.pitch || register === "above" && pitch <= melodyVoice.pitch)) {
|
|
1852
1929
|
return null;
|
|
1853
1930
|
}
|
|
1854
|
-
const result =
|
|
1931
|
+
const result = _chunkYDGMWH43cjs.evaluateSafety.call(void 0,
|
|
1855
1932
|
{
|
|
1856
1933
|
profile,
|
|
1857
1934
|
candidatePitch: pitch,
|
|
@@ -1873,51 +1950,51 @@ function heldPitchSafety(pitch, contexts, prevPitch, key, profile, register, low
|
|
|
1873
1950
|
return worst;
|
|
1874
1951
|
}
|
|
1875
1952
|
function generateCounterMelody(opts) {
|
|
1876
|
-
|
|
1953
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "countermelody options");
|
|
1877
1954
|
const timeline = opts.timeline;
|
|
1878
1955
|
const chordAt = timeline === void 0 ? opts.chordAt : (beat) => timeline.at(beat);
|
|
1879
1956
|
if (chordAt === void 0) {
|
|
1880
|
-
throw new (0,
|
|
1957
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("countermelody needs a timeline or a chordAt callback");
|
|
1881
1958
|
}
|
|
1882
1959
|
const chordChangeBeats = timeline === void 0 ? _nullishCoalesce(opts.chordChangeBeats, () => ( [])) : timeline.segments.flatMap((segment) => [segment.startBeat, segment.endBeat]);
|
|
1883
|
-
const register = _nullishCoalesce(opts.register, () => ( "below"));
|
|
1884
|
-
|
|
1885
|
-
const melody =
|
|
1960
|
+
const register = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.register, () => ( "below")), ["above", "below"], "register");
|
|
1961
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, opts.melody, "countermelody melody", { allowNonPositiveDuration: true });
|
|
1962
|
+
const melody = _chunkKMYGRFZ6cjs.createNoteEventIndex.call(void 0, _chunkS3QELJUEcjs.soundingNotesOnly.call(void 0, opts.melody), {
|
|
1886
1963
|
tieBreak: register === "below" ? "highest" : "lowest"
|
|
1887
1964
|
});
|
|
1888
|
-
const ts =
|
|
1889
|
-
|
|
1890
|
-
const rhythm =
|
|
1891
|
-
const profile =
|
|
1965
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_TS2)), "ts"));
|
|
1966
|
+
_chunkS3QELJUEcjs.assertTimeSignature.call(void 0, ts);
|
|
1967
|
+
const rhythm = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.rhythm, () => ( "complement")), ["complement", "follow"], "rhythm");
|
|
1968
|
+
const profile = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.profile, () => ( "pop")), ["strict", "pop"], "safety profile");
|
|
1892
1969
|
assertWeightOverrides(opts.weights);
|
|
1893
|
-
const weights =
|
|
1894
|
-
const key =
|
|
1970
|
+
const weights = _chunkYDGMWH43cjs.profileWeights.call(void 0, profile, opts.weights);
|
|
1971
|
+
const key = _chunkYDGMWH43cjs.toKeyScale.call(void 0, opts.key);
|
|
1895
1972
|
const draw = resolveContext(opts.ctx).part("countermelody");
|
|
1896
1973
|
if (melody.notes.length === 0) {
|
|
1897
1974
|
return [];
|
|
1898
1975
|
}
|
|
1899
|
-
const spanStart = _nullishCoalesce(_optionalChain([melody, 'access',
|
|
1976
|
+
const spanStart = _nullishCoalesce(_optionalChain([melody, 'access', _24 => _24.notes, 'access', _25 => _25[0], 'optionalAccess', _26 => _26.note, 'access', _27 => _27.startBeat]), () => ( 0));
|
|
1900
1977
|
const spanEnd = melody.notes.reduce((end, n) => Math.max(end, n.endBeat), spanStart);
|
|
1901
|
-
|
|
1978
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, Math.ceil((spanEnd - spanStart) / GRID_STEP), "countermelody grid");
|
|
1902
1979
|
const meanPitch = melody.notes.reduce((sum, n) => sum + n.note.pitch, 0) / melody.notes.length;
|
|
1903
1980
|
const defaultCenter = register === "below" ? meanPitch - REGISTER_OFFSET : meanPitch + REGISTER_OFFSET;
|
|
1904
|
-
const low =
|
|
1981
|
+
const low = _chunkS3QELJUEcjs.clampToMidi.call(void 0,
|
|
1905
1982
|
_nullishCoalesce(opts.pitchLow, () => ( Math.round(defaultCenter) - DEFAULT_HALF_RANGE)),
|
|
1906
1983
|
"countermelody pitchLow"
|
|
1907
1984
|
);
|
|
1908
|
-
const high =
|
|
1985
|
+
const high = _chunkS3QELJUEcjs.clampToMidi.call(void 0,
|
|
1909
1986
|
_nullishCoalesce(opts.pitchHigh, () => ( Math.round(defaultCenter) + DEFAULT_HALF_RANGE)),
|
|
1910
1987
|
"countermelody pitchHigh"
|
|
1911
1988
|
);
|
|
1912
1989
|
if (low > high) {
|
|
1913
|
-
throw new (0,
|
|
1990
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
1914
1991
|
`countermelody pitchLow must not exceed pitchHigh; received ${low} > ${high}`
|
|
1915
1992
|
);
|
|
1916
1993
|
}
|
|
1917
|
-
|
|
1918
|
-
|
|
1994
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, high - low + 1, "countermelody pitch candidates");
|
|
1995
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, chordChangeBeats.length, "chord change beats");
|
|
1919
1996
|
for (let index = 0; index < chordChangeBeats.length; index += 1) {
|
|
1920
|
-
|
|
1997
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0,
|
|
1921
1998
|
_nullishCoalesce(chordChangeBeats[index], () => ( Number.NaN)),
|
|
1922
1999
|
0,
|
|
1923
2000
|
Number.MAX_SAFE_INTEGER,
|
|
@@ -1927,7 +2004,7 @@ function generateCounterMelody(opts) {
|
|
|
1927
2004
|
const center = (low + high) / 2;
|
|
1928
2005
|
const onsets = rhythm === "follow" ? followOnsets(melody) : complementOnsets(melody, ts, spanStart, spanEnd, draw);
|
|
1929
2006
|
const boundaryEstimate = onsets.length + Math.ceil((spanEnd - spanStart) / GRID_STEP) + melody.notes.length + chordChangeBeats.length;
|
|
1930
|
-
|
|
2007
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, boundaryEstimate * (high - low + 1), "countermelody search");
|
|
1931
2008
|
const jitter = Array.from(
|
|
1932
2009
|
{ length: high - low + 1 },
|
|
1933
2010
|
(_, index) => draw.at("jitter", index) * TIE_BREAK_JITTER
|
|
@@ -1942,20 +2019,20 @@ function generateCounterMelody(opts) {
|
|
|
1942
2019
|
const nextOnset = onsets[onsetIndex + 1];
|
|
1943
2020
|
const endBeat = _nullishCoalesce(nextOnset, () => ( Math.max(spanEnd, beat + GRID_STEP)));
|
|
1944
2021
|
const melNote = melodyNoteAt(melody, beat);
|
|
1945
|
-
const melPitch = _optionalChain([melNote, 'optionalAccess',
|
|
2022
|
+
const melPitch = _optionalChain([melNote, 'optionalAccess', _28 => _28.pitch]);
|
|
1946
2023
|
const melodyVoice = melodySnapshotAt(melody, beat);
|
|
1947
|
-
const melPrev = _optionalChain([melodyVoice, 'optionalAccess',
|
|
2024
|
+
const melPrev = _optionalChain([melodyVoice, 'optionalAccess', _29 => _29.prevPitch]);
|
|
1948
2025
|
const contexts = boundaryContexts(melody, { chordAt, chordChangeBeats }, beat, endBeat, ts);
|
|
1949
|
-
const chord = _nullishCoalesce(_optionalChain([contexts, 'access',
|
|
2026
|
+
const chord = _nullishCoalesce(_optionalChain([contexts, 'access', _30 => _30[0], 'optionalAccess', _31 => _31.chord]), () => ( chordAt(beat)));
|
|
1950
2027
|
const otherVoices = melodyVoice !== void 0 ? [melodyVoice] : [];
|
|
1951
|
-
const candidates =
|
|
2028
|
+
const candidates = _chunkYDGMWH43cjs.enumerateSafePitches.call(void 0,
|
|
1952
2029
|
{
|
|
1953
2030
|
profile,
|
|
1954
2031
|
prevPitch,
|
|
1955
2032
|
chord,
|
|
1956
2033
|
key,
|
|
1957
2034
|
otherVoices,
|
|
1958
|
-
strongBeat:
|
|
2035
|
+
strongBeat: _chunkS3QELJUEcjs.isStrongBeat.call(void 0, beat, ts),
|
|
1959
2036
|
vocalLow: low,
|
|
1960
2037
|
vocalHigh: high
|
|
1961
2038
|
},
|
|
@@ -1982,7 +2059,7 @@ function generateCounterMelody(opts) {
|
|
|
1982
2059
|
if (melPitch !== void 0) {
|
|
1983
2060
|
if (prevPitch !== void 0 && melPrev !== void 0 && // Parallel octaves are the perfect-class-zero case of this predicate,
|
|
1984
2061
|
// so a single check covers both parallel fifths and octaves.
|
|
1985
|
-
|
|
2062
|
+
_chunkYDGMWH43cjs.createsParallelPerfect.call(void 0, prevPitch, candidate, melPrev, melPitch)) {
|
|
1986
2063
|
continue;
|
|
1987
2064
|
}
|
|
1988
2065
|
}
|
|
@@ -2001,10 +2078,10 @@ function generateCounterMelody(opts) {
|
|
|
2001
2078
|
const pitch = bestPitch;
|
|
2002
2079
|
const velocity = Math.max(
|
|
2003
2080
|
1,
|
|
2004
|
-
Math.min(127, Math.round((_nullishCoalesce(_optionalChain([melNote, 'optionalAccess',
|
|
2081
|
+
Math.min(127, Math.round((_nullishCoalesce(_optionalChain([melNote, 'optionalAccess', _32 => _32.velocity]), () => ( DEFAULT_MELODY_VELOCITY))) - VELOCITY_DROP))
|
|
2005
2082
|
);
|
|
2006
2083
|
out.push({
|
|
2007
|
-
pitch:
|
|
2084
|
+
pitch: _chunkS3QELJUEcjs.clampToMidi.call(void 0, pitch),
|
|
2008
2085
|
startBeat: beat,
|
|
2009
2086
|
durationBeat: endBeat - beat,
|
|
2010
2087
|
velocity
|
|
@@ -2113,13 +2190,14 @@ function denser(level) {
|
|
|
2113
2190
|
}
|
|
2114
2191
|
return "sixteenth";
|
|
2115
2192
|
}
|
|
2193
|
+
var LEVEL_ORDER = ["quarter", "eighth", "sixteenth"];
|
|
2116
2194
|
function hiHatStep(level) {
|
|
2117
2195
|
if (level === "sixteenth") {
|
|
2118
2196
|
return 0.25;
|
|
2119
2197
|
}
|
|
2120
2198
|
return level === "eighth" ? 0.5 : 1;
|
|
2121
2199
|
}
|
|
2122
|
-
function
|
|
2200
|
+
function getHiHatBar(section, style, rhythmic, bpm, draw, difficulty, bar2) {
|
|
2123
2201
|
const allow16th = bpm < HH_16TH_BPM_THRESHOLD;
|
|
2124
2202
|
let base = "eighth";
|
|
2125
2203
|
let dialed = true;
|
|
@@ -2159,22 +2237,41 @@ function getHiHatLevel(section, style, rhythmic, bpm, draw, difficulty, bar2) {
|
|
|
2159
2237
|
break;
|
|
2160
2238
|
}
|
|
2161
2239
|
}
|
|
2240
|
+
const playable = (proposed) => {
|
|
2241
|
+
let level2 = !allow16th && proposed === "sixteenth" ? "eighth" : proposed;
|
|
2242
|
+
while (level2 !== "quarter" && !sustainsStrokes(hiHatStep(level2), bpm, difficulty)) {
|
|
2243
|
+
level2 = sparser(level2);
|
|
2244
|
+
}
|
|
2245
|
+
return level2;
|
|
2246
|
+
};
|
|
2162
2247
|
let level = base;
|
|
2248
|
+
let thinnedUpTo = Number.NEGATIVE_INFINITY;
|
|
2249
|
+
let filledAbove = Number.POSITIVE_INFINITY;
|
|
2163
2250
|
if (dialed) {
|
|
2164
|
-
|
|
2251
|
+
const thin2 = draw.at("hhThin", bar2);
|
|
2252
|
+
if (thin2 >= 2 * rhythmic) {
|
|
2165
2253
|
level = sparser(level);
|
|
2166
2254
|
}
|
|
2167
|
-
|
|
2255
|
+
const fill2 = draw.at("hhFill", bar2);
|
|
2256
|
+
if (fill2 < 2 * rhythmic - 1) {
|
|
2168
2257
|
level = denser(level);
|
|
2169
2258
|
}
|
|
2259
|
+
thinnedUpTo = thin2 / 2;
|
|
2260
|
+
filledAbove = (fill2 + 1) / 2;
|
|
2170
2261
|
}
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2262
|
+
const rank = (candidate) => LEVEL_ORDER.indexOf(candidate);
|
|
2263
|
+
const sparsest = rank(playable(dialed ? sparser(base) : base));
|
|
2264
|
+
const middle = rank(playable(base));
|
|
2265
|
+
const densest = rank(playable(dialed ? denser(base) : base));
|
|
2266
|
+
const entryOf = (grid) => sparsest >= rank(grid) ? Number.NEGATIVE_INFINITY : middle >= rank(grid) ? thinnedUpTo : densest >= rank(grid) ? filledAbove : Number.POSITIVE_INFINITY;
|
|
2267
|
+
return {
|
|
2268
|
+
level: playable(level),
|
|
2269
|
+
entries: {
|
|
2270
|
+
quarter: entryOf("quarter"),
|
|
2271
|
+
eighth: entryOf("eighth"),
|
|
2272
|
+
sixteenth: entryOf("sixteenth")
|
|
2273
|
+
}
|
|
2274
|
+
};
|
|
2178
2275
|
}
|
|
2179
2276
|
function hiHatVelocityMultiplier(sixteenth, jitter) {
|
|
2180
2277
|
switch (sixteenth) {
|
|
@@ -2385,11 +2482,12 @@ function generateKickForBeat(ctx, sec, kick) {
|
|
|
2385
2482
|
const sixteenths = kick.length / 4;
|
|
2386
2483
|
for (let step = 0; step < sixteenths; step += 1) {
|
|
2387
2484
|
const index = ctx.beat * sixteenths + step;
|
|
2388
|
-
|
|
2485
|
+
const entry = kick[index];
|
|
2486
|
+
if (entry === void 0) {
|
|
2389
2487
|
continue;
|
|
2390
2488
|
}
|
|
2391
2489
|
if (step === 0) {
|
|
2392
|
-
ctx.track.add(GM.BD, ctx.beatTick, EIGHTH, ctx.velocity);
|
|
2490
|
+
ctx.track.add(GM.BD, ctx.beatTick, EIGHTH, ctx.velocity, void 0, entry);
|
|
2393
2491
|
continue;
|
|
2394
2492
|
}
|
|
2395
2493
|
const offBeat = step % 2 === 1;
|
|
@@ -2397,7 +2495,7 @@ function generateKickForBeat(ctx, sec, kick) {
|
|
|
2397
2495
|
continue;
|
|
2398
2496
|
}
|
|
2399
2497
|
const tick = swing16(ctx.beatTick + step * SIXTEENTH, sec, ctx.swingAmount);
|
|
2400
|
-
ctx.track.add(GM.BD, tick, offBeat ? SIXTEENTH : EIGHTH, ctx.velocity * 0.85);
|
|
2498
|
+
ctx.track.add(GM.BD, tick, offBeat ? SIXTEENTH : EIGHTH, ctx.velocity * 0.85, void 0, entry);
|
|
2401
2499
|
}
|
|
2402
2500
|
}
|
|
2403
2501
|
function roleBackbeatWeight(role) {
|
|
@@ -2450,16 +2548,19 @@ function generateGhostNotesForBeat(ctx, sec) {
|
|
|
2450
2548
|
return;
|
|
2451
2549
|
}
|
|
2452
2550
|
const positions = selectGhostPositions(sec.ghostMood);
|
|
2453
|
-
|
|
2551
|
+
const ghostDensity = getGhostDensity(sec.ghostMood, ctx.section, ctx.bpm);
|
|
2552
|
+
let ghostProb = leanedBy(ghostDensity, sec.ornament);
|
|
2454
2553
|
if (sec.ghostBoost) {
|
|
2455
2554
|
ghostProb = Math.min(1, ghostProb * 1.4);
|
|
2456
2555
|
}
|
|
2457
2556
|
for (const pos of positions) {
|
|
2458
2557
|
const sixteenthInBeat = pos === "e" ? 1 : 3;
|
|
2459
2558
|
const posProb = getGhostProbabilityAtPosition(ctx.beat, sixteenthInBeat, leadIns);
|
|
2460
|
-
|
|
2559
|
+
const at2 = ctx.draw.at("ghost", ctx.bar, ctx.beat, pos);
|
|
2560
|
+
if (!(at2 < ghostProb * posProb)) {
|
|
2461
2561
|
continue;
|
|
2462
2562
|
}
|
|
2563
|
+
const entry = sec.ornamentFollowsRhythmic ? at2 / (posProb * (sec.ghostBoost ? 1.4 : 1) * ghostDensity) - 0.5 : Number.NEGATIVE_INFINITY;
|
|
2463
2564
|
const variation = ctx.draw.float(0.85, 1.15, "ghostVelocity", ctx.bar, ctx.beat, pos);
|
|
2464
2565
|
const ghostBase = getGhostVelocity(ctx.section, ctx.beat / 2);
|
|
2465
2566
|
let ghostVel = ctx.velocity * ghostBase * variation;
|
|
@@ -2468,7 +2569,7 @@ function generateGhostNotesForBeat(ctx, sec) {
|
|
|
2468
2569
|
}
|
|
2469
2570
|
const offset = pos === "e" ? SIXTEENTH : 3 * SIXTEENTH;
|
|
2470
2571
|
const tick = swing16(ctx.beatTick + offset, sec, ctx.swingAmount);
|
|
2471
|
-
ctx.track.add(GM.SD, tick, SIXTEENTH, ghostVel);
|
|
2572
|
+
ctx.track.add(GM.SD, tick, SIXTEENTH, ghostVel, void 0, entry);
|
|
2472
2573
|
}
|
|
2473
2574
|
}
|
|
2474
2575
|
function generatePreChorusBuildup(ctx, sec, isSectionLastBar) {
|
|
@@ -2526,17 +2627,25 @@ function generateHiHatForBeat(ctx, sec) {
|
|
|
2526
2627
|
const allowsOpenHiHat = sec.role !== "ambient" && sec.role !== "minimal";
|
|
2527
2628
|
const isDynamicOpen = ctx.barHasOpenHh && ctx.beat === ctx.openHhBeat && !usesOffbeatOpenHiHat(sec.style);
|
|
2528
2629
|
const dm = sec.densityMult;
|
|
2630
|
+
const beatEntry = ctx.section === "intro" && ctx.beat !== 0 ? ctx.hhEntries.eighth : ctx.hhEntries.quarter;
|
|
2529
2631
|
if (ctx.hhLevel === "quarter") {
|
|
2530
2632
|
if (ctx.section === "intro" && ctx.beat !== 0) {
|
|
2531
2633
|
return;
|
|
2532
2634
|
}
|
|
2533
2635
|
const hhVel = Math.max(20, ctx.velocity * dm * 0.75 * typeMult);
|
|
2534
2636
|
if (allowsOpenHiHat && isDynamicOpen) {
|
|
2535
|
-
ctx.track.add(GM.OHH, ctx.beatTick, EIGHTH, hhVel + OHH_VEL_BOOST);
|
|
2637
|
+
ctx.track.add(GM.OHH, ctx.beatTick, EIGHTH, hhVel + OHH_VEL_BOOST, void 0, beatEntry);
|
|
2536
2638
|
} else if (allowsOpenHiHat && opensOnDownbeat(ctx, sec)) {
|
|
2537
|
-
ctx.track.add(
|
|
2639
|
+
ctx.track.add(
|
|
2640
|
+
hiHatNote("open"),
|
|
2641
|
+
ctx.beatTick,
|
|
2642
|
+
EIGHTH,
|
|
2643
|
+
Math.max(20, hhVel * 1.1),
|
|
2644
|
+
void 0,
|
|
2645
|
+
beatEntry
|
|
2646
|
+
);
|
|
2538
2647
|
} else {
|
|
2539
|
-
ctx.track.add(hhInstrument, ctx.beatTick, EIGHTH, hhVel);
|
|
2648
|
+
ctx.track.add(hhInstrument, ctx.beatTick, EIGHTH, hhVel, void 0, beatEntry);
|
|
2540
2649
|
}
|
|
2541
2650
|
return;
|
|
2542
2651
|
}
|
|
@@ -2546,22 +2655,37 @@ function generateHiHatForBeat(ctx, sec) {
|
|
|
2546
2655
|
if (eighth === 1) {
|
|
2547
2656
|
hhTick = swing16(hhTick, sec, ctx.swingAmount);
|
|
2548
2657
|
}
|
|
2658
|
+
const entry = eighth === 0 ? beatEntry : ctx.hhEntries.eighth;
|
|
2549
2659
|
if (ctx.section === "intro" && eighth === 1) {
|
|
2550
2660
|
if (sec.useFootHh && ctx.beat % 2 === 0) {
|
|
2551
|
-
ctx.track.add(
|
|
2661
|
+
ctx.track.add(
|
|
2662
|
+
GM.FHH,
|
|
2663
|
+
hhTick,
|
|
2664
|
+
EIGHTH,
|
|
2665
|
+
footHiHatVelocity(ctx.draw, ctx.bar, ctx.beat),
|
|
2666
|
+
void 0,
|
|
2667
|
+
entry
|
|
2668
|
+
);
|
|
2552
2669
|
}
|
|
2553
2670
|
continue;
|
|
2554
2671
|
}
|
|
2555
2672
|
const hhVel = Math.max(20, ctx.velocity * dm * typeMult * (eighth === 0 ? 0.9 : 0.65));
|
|
2556
2673
|
if (isDynamicOpen && allowsOpenHiHat && eighth === 0) {
|
|
2557
|
-
ctx.track.add(GM.OHH, hhTick, EIGHTH, hhVel + OHH_VEL_BOOST);
|
|
2674
|
+
ctx.track.add(GM.OHH, hhTick, EIGHTH, hhVel + OHH_VEL_BOOST, void 0, entry);
|
|
2558
2675
|
continue;
|
|
2559
2676
|
}
|
|
2560
2677
|
const useOpen = eighth === 0 ? opensOnDownbeat(ctx, sec) : opensOffbeat(ctx, sec);
|
|
2561
2678
|
if (useOpen && allowsOpenHiHat) {
|
|
2562
|
-
ctx.track.add(
|
|
2679
|
+
ctx.track.add(
|
|
2680
|
+
hiHatNote("open"),
|
|
2681
|
+
hhTick,
|
|
2682
|
+
EIGHTH,
|
|
2683
|
+
Math.max(20, hhVel * 1.1),
|
|
2684
|
+
void 0,
|
|
2685
|
+
entry
|
|
2686
|
+
);
|
|
2563
2687
|
} else {
|
|
2564
|
-
ctx.track.add(hhInstrument, hhTick, EIGHTH / 2, hhVel);
|
|
2688
|
+
ctx.track.add(hhInstrument, hhTick, EIGHTH / 2, hhVel, void 0, entry);
|
|
2565
2689
|
}
|
|
2566
2690
|
}
|
|
2567
2691
|
return;
|
|
@@ -2576,35 +2700,50 @@ function generateHiHatForBeat(ctx, sec) {
|
|
|
2576
2700
|
ctx.draw.float(0.95, 1.05, "hatVelocity", ctx.bar, ctx.beat, sixteenth)
|
|
2577
2701
|
);
|
|
2578
2702
|
const hhVel = Math.max(20, ctx.velocity * dm * typeMult * metricVel);
|
|
2703
|
+
const entry = sixteenth === 0 ? beatEntry : sixteenth === 2 ? ctx.hhEntries.eighth : ctx.hhEntries.sixteenth;
|
|
2579
2704
|
if (isDynamicOpen && allowsOpenHiHat && sixteenth === 0) {
|
|
2580
|
-
ctx.track.add(GM.OHH, hhTick, SIXTEENTH, hhVel + OHH_VEL_BOOST);
|
|
2705
|
+
ctx.track.add(GM.OHH, hhTick, SIXTEENTH, hhVel + OHH_VEL_BOOST, void 0, entry);
|
|
2581
2706
|
continue;
|
|
2582
2707
|
}
|
|
2583
2708
|
if (allowsOpenHiHat && sixteenth === 0 && opensOnDownbeat(ctx, sec)) {
|
|
2584
|
-
ctx.track.add(
|
|
2709
|
+
ctx.track.add(
|
|
2710
|
+
hiHatNote("open"),
|
|
2711
|
+
hhTick,
|
|
2712
|
+
SIXTEENTH,
|
|
2713
|
+
Math.max(20, hhVel * 1.1),
|
|
2714
|
+
void 0,
|
|
2715
|
+
entry
|
|
2716
|
+
);
|
|
2585
2717
|
continue;
|
|
2586
2718
|
}
|
|
2587
2719
|
if (allowsOpenHiHat && sixteenth === 2 && opensOffbeat(ctx, sec)) {
|
|
2588
|
-
ctx.track.add(
|
|
2720
|
+
ctx.track.add(
|
|
2721
|
+
hiHatNote("open"),
|
|
2722
|
+
hhTick,
|
|
2723
|
+
SIXTEENTH,
|
|
2724
|
+
Math.max(20, hhVel * 1.1),
|
|
2725
|
+
void 0,
|
|
2726
|
+
entry
|
|
2727
|
+
);
|
|
2589
2728
|
continue;
|
|
2590
2729
|
}
|
|
2591
2730
|
if (allowsOpenHiHat && ctx.beat === 3 && sixteenth === 3) {
|
|
2592
2731
|
const openProb = Math.max(0.1, Math.min(0.4, 30 / ctx.bpm));
|
|
2593
2732
|
if (ctx.draw.prob(openProb, "openHat", ctx.bar, ctx.beat, sixteenth)) {
|
|
2594
|
-
ctx.track.add(GM.OHH, hhTick, SIXTEENTH, Math.max(20, hhVel * 1.2));
|
|
2733
|
+
ctx.track.add(GM.OHH, hhTick, SIXTEENTH, Math.max(20, hhVel * 1.2), void 0, entry);
|
|
2595
2734
|
continue;
|
|
2596
2735
|
}
|
|
2597
2736
|
}
|
|
2598
|
-
ctx.track.add(hhInstrument, hhTick, SIXTEENTH / 2, hhVel);
|
|
2737
|
+
ctx.track.add(hhInstrument, hhTick, SIXTEENTH / 2, hhVel, void 0, entry);
|
|
2599
2738
|
}
|
|
2600
2739
|
}
|
|
2601
2740
|
|
|
2602
2741
|
// src/generate/drums/euclid.ts
|
|
2603
2742
|
function euclideanRhythm(pulses, steps, rotation = 0) {
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2743
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, steps, "euclidean steps");
|
|
2744
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, pulses, "euclidean pulses");
|
|
2745
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, rotation, "euclidean rotation");
|
|
2746
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, steps, "euclidean pattern steps");
|
|
2608
2747
|
const p = Math.max(0, Math.min(pulses, steps));
|
|
2609
2748
|
const base = bjorklund(p, steps);
|
|
2610
2749
|
const shift = (rotation % steps + steps) % steps;
|
|
@@ -2622,7 +2761,7 @@ function bjorklund(pulses, steps) {
|
|
|
2622
2761
|
}
|
|
2623
2762
|
let head = Array.from({ length: pulses }, () => [true]);
|
|
2624
2763
|
let remainder = Array.from({ length: steps - pulses }, () => [false]);
|
|
2625
|
-
|
|
2764
|
+
do {
|
|
2626
2765
|
const count = Math.min(head.length, remainder.length);
|
|
2627
2766
|
const next = [];
|
|
2628
2767
|
for (let i = 0; i < count; i += 1) {
|
|
@@ -2630,7 +2769,7 @@ function bjorklund(pulses, steps) {
|
|
|
2630
2769
|
}
|
|
2631
2770
|
remainder = head.length > count ? head.slice(count) : remainder.slice(count);
|
|
2632
2771
|
head = next;
|
|
2633
|
-
}
|
|
2772
|
+
} while (remainder.length > 1);
|
|
2634
2773
|
return [...head.flat(), ...remainder.flat()];
|
|
2635
2774
|
}
|
|
2636
2775
|
|
|
@@ -2650,6 +2789,7 @@ var FILL_TYPES = Object.freeze([
|
|
|
2650
2789
|
"flamsAndDrags",
|
|
2651
2790
|
"halfTimeFill"
|
|
2652
2791
|
]);
|
|
2792
|
+
var FILL_VELOCITY_BASES = Object.freeze(["fill", "accent"]);
|
|
2653
2793
|
var S = SIXTEENTH;
|
|
2654
2794
|
var E = EIGHTH;
|
|
2655
2795
|
function fill(scale, offset) {
|
|
@@ -2773,8 +2913,31 @@ var FILL_ARCHETYPES = deepFreeze({
|
|
|
2773
2913
|
function isFillArchetype(material) {
|
|
2774
2914
|
return typeof material === "object" && material !== null && Array.isArray(material.atBeat);
|
|
2775
2915
|
}
|
|
2916
|
+
function assertFillArchetype(material, label) {
|
|
2917
|
+
material.atBeat.forEach((beat, beatIndex) => {
|
|
2918
|
+
const strokes = _chunkS3QELJUEcjs.assertArray.call(void 0, beat, `${label} atBeat[${beatIndex}]`);
|
|
2919
|
+
strokes.forEach((given, strokeIndex) => {
|
|
2920
|
+
const name = `${label} atBeat[${beatIndex}][${strokeIndex}]`;
|
|
2921
|
+
const stroke = _chunkS3QELJUEcjs.assertRecord.call(void 0, given, name);
|
|
2922
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, stroke.voice, `${name}.voice`);
|
|
2923
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, stroke.offset, `${name}.offset`);
|
|
2924
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, stroke.duration, `${name}.duration`);
|
|
2925
|
+
const velocity = _chunkS3QELJUEcjs.assertRecord.call(void 0, stroke.velocity, `${name}.velocity`);
|
|
2926
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, velocity.base, FILL_VELOCITY_BASES, `${name}.velocity.base`);
|
|
2927
|
+
if (velocity.scale !== void 0) {
|
|
2928
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, velocity.scale, `${name}.velocity.scale`);
|
|
2929
|
+
}
|
|
2930
|
+
if (velocity.offset !== void 0) {
|
|
2931
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, velocity.offset, -127, 127, `${name}.velocity.offset`);
|
|
2932
|
+
}
|
|
2933
|
+
if (stroke.articulation !== void 0) {
|
|
2934
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, stroke.articulation, _chunkS3QELJUEcjs.ARTICULATIONS, `${name}.articulation`);
|
|
2935
|
+
}
|
|
2936
|
+
});
|
|
2937
|
+
});
|
|
2938
|
+
}
|
|
2776
2939
|
function fillArchetypeFor(id, supplied) {
|
|
2777
|
-
return _nullishCoalesce(_optionalChain([supplied, 'optionalAccess',
|
|
2940
|
+
return _nullishCoalesce(_optionalChain([supplied, 'optionalAccess', _33 => _33.get, 'call', _34 => _34(id)]), () => ( FILL_ARCHETYPES[id]));
|
|
2778
2941
|
}
|
|
2779
2942
|
function getFillStartBeat(energy) {
|
|
2780
2943
|
switch (energy) {
|
|
@@ -2940,13 +3103,15 @@ function drumNoteOf(voice) {
|
|
|
2940
3103
|
return Object.hasOwn(DRUM_NOTES, voice) ? DRUM_NOTES[voice] : void 0;
|
|
2941
3104
|
}
|
|
2942
3105
|
function drumVoiceOf(pitch) {
|
|
2943
|
-
return VOICE_BY_NOTE.get(
|
|
3106
|
+
return VOICE_BY_NOTE.get(_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, pitch));
|
|
2944
3107
|
}
|
|
2945
3108
|
var ONSET_KEY_SCALE = 128;
|
|
2946
3109
|
var HitList = (_class = class {constructor() { _class.prototype.__init.call(this); }
|
|
2947
3110
|
__init() {this.hits = []}
|
|
2948
3111
|
/** Voices already struck at each quantized beat. */
|
|
2949
3112
|
#onsets = /* @__PURE__ */ new Map();
|
|
3113
|
+
/** The rhythmic-dial setting each onset enters at, by onset key; absent is always. */
|
|
3114
|
+
#entries = /* @__PURE__ */ new Map();
|
|
2950
3115
|
/**
|
|
2951
3116
|
* Append a hit, clamping velocity and dropping non-positive positions.
|
|
2952
3117
|
*
|
|
@@ -2954,12 +3119,23 @@ var HitList = (_class = class {constructor() { _class.prototype.__init.call(this
|
|
|
2954
3119
|
* sounds once however many voices ask for it, and a second entry at the same
|
|
2955
3120
|
* pitch and position is a note-on a reader answers with no note-off, heard as
|
|
2956
3121
|
* a hung or cut stroke rather than as a louder one.
|
|
3122
|
+
*
|
|
3123
|
+
* `entry` is the rhythmic-dial setting above which the stroke sounds, for a
|
|
3124
|
+
* stroke the dial adds; a stroke asked for twice sounds from the lower one.
|
|
2957
3125
|
*/
|
|
2958
|
-
add(pitch, startBeat, durationBeat, velocity, articulation) {
|
|
3126
|
+
add(pitch, startBeat, durationBeat, velocity, articulation, entry = Number.NEGATIVE_INFINITY) {
|
|
2959
3127
|
const beat = Math.max(0, startBeat);
|
|
3128
|
+
const key = onsetKey(pitch, beat);
|
|
3129
|
+
const held = this.#entries.get(key);
|
|
2960
3130
|
if (this.hasOnset(pitch, beat)) {
|
|
3131
|
+
if (held !== void 0 && entry < held) {
|
|
3132
|
+
this.#entries.set(key, entry);
|
|
3133
|
+
}
|
|
2961
3134
|
return;
|
|
2962
3135
|
}
|
|
3136
|
+
if (entry !== Number.NEGATIVE_INFINITY) {
|
|
3137
|
+
this.#entries.set(key, entry);
|
|
3138
|
+
}
|
|
2963
3139
|
const hit2 = {
|
|
2964
3140
|
pitch,
|
|
2965
3141
|
startBeat: beat,
|
|
@@ -2977,9 +3153,16 @@ var HitList = (_class = class {constructor() { _class.prototype.__init.call(this
|
|
|
2977
3153
|
this.#onsets.set(beatSlot(beat), /* @__PURE__ */ new Set([pitch]));
|
|
2978
3154
|
}
|
|
2979
3155
|
}
|
|
3156
|
+
/**
|
|
3157
|
+
* The rhythmic-dial setting above which a written stroke sounds: minus
|
|
3158
|
+
* infinity for one that sounds at every setting.
|
|
3159
|
+
*/
|
|
3160
|
+
entryOf(pitch, startBeat) {
|
|
3161
|
+
return _nullishCoalesce(this.#entries.get(onsetKey(pitch, startBeat)), () => ( Number.NEGATIVE_INFINITY));
|
|
3162
|
+
}
|
|
2980
3163
|
/** Whether a hit of this pitch already starts exactly at `startBeat`. */
|
|
2981
3164
|
hasOnset(pitch, startBeat) {
|
|
2982
|
-
return _nullishCoalesce(_optionalChain([this, 'access',
|
|
3165
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _35 => _35.#onsets, 'access', _36 => _36.get, 'call', _37 => _37(beatSlot(startBeat)), 'optionalAccess', _38 => _38.has, 'call', _39 => _39(pitch)]), () => ( false));
|
|
2983
3166
|
}
|
|
2984
3167
|
/**
|
|
2985
3168
|
* True when a crash already sits less than a 16th from `startBeat`, on either
|
|
@@ -3073,17 +3256,14 @@ var KICK_FIGURES = deepFreeze({
|
|
|
3073
3256
|
],
|
|
3074
3257
|
standard: DEFAULT_FIGURE
|
|
3075
3258
|
});
|
|
3076
|
-
function emptyPattern() {
|
|
3077
|
-
return Array.from({ length: KICK_STEPS }, () => false);
|
|
3078
|
-
}
|
|
3079
3259
|
function isInPreChorusLift(section, bar2, sectionBars, nextIsChorus) {
|
|
3080
3260
|
if (section !== "b" || !nextIsChorus || sectionBars < 3) {
|
|
3081
3261
|
return false;
|
|
3082
3262
|
}
|
|
3083
3263
|
return bar2 >= sectionBars - 2;
|
|
3084
3264
|
}
|
|
3085
|
-
function
|
|
3086
|
-
const
|
|
3265
|
+
function realiseKickEntries(figure, section, bar2, draw, rhythmic) {
|
|
3266
|
+
const entries = Array.from({ length: KICK_STEPS }, () => void 0);
|
|
3087
3267
|
for (const slot of figure) {
|
|
3088
3268
|
if (slot.step < 0 || slot.step >= KICK_STEPS) {
|
|
3089
3269
|
continue;
|
|
@@ -3095,19 +3275,23 @@ function realiseKickFigure(figure, section, bar2, draw, rhythmic) {
|
|
|
3095
3275
|
continue;
|
|
3096
3276
|
}
|
|
3097
3277
|
if (slot.probability === void 0) {
|
|
3098
|
-
|
|
3278
|
+
entries[slot.step] = Number.NEGATIVE_INFINITY;
|
|
3099
3279
|
continue;
|
|
3100
3280
|
}
|
|
3101
|
-
|
|
3102
|
-
|
|
3281
|
+
const at2 = draw.at("kick", bar2, _nullishCoalesce(slot.slot, () => ( slot.step)));
|
|
3282
|
+
if (at2 < leanedBy(slot.probability, rhythmic)) {
|
|
3283
|
+
entries[slot.step] = Math.min(
|
|
3284
|
+
_nullishCoalesce(entries[slot.step], () => ( Number.POSITIVE_INFINITY)),
|
|
3285
|
+
at2 / slot.probability - 0.5
|
|
3286
|
+
);
|
|
3103
3287
|
}
|
|
3104
3288
|
}
|
|
3105
|
-
return
|
|
3289
|
+
return entries;
|
|
3106
3290
|
}
|
|
3107
|
-
function
|
|
3291
|
+
function getKickEntries(section, style, bar2, draw, rhythmic) {
|
|
3108
3292
|
const own = _nullishCoalesce(KICK_FIGURES[style], () => ( DEFAULT_FIGURE));
|
|
3109
3293
|
const figure = section === "outro" ? [...OUTRO_FIGURE, ...statedSlots(own)] : own;
|
|
3110
|
-
return
|
|
3294
|
+
return realiseKickEntries(figure, section, bar2, draw, rhythmic);
|
|
3111
3295
|
}
|
|
3112
3296
|
|
|
3113
3297
|
// src/generate/drums/percussion.ts
|
|
@@ -3144,9 +3328,11 @@ var PERC_TABLE = [
|
|
|
3144
3328
|
/* rock */
|
|
3145
3329
|
[F, F, F, [false, false, true], F, F, F, F, [false, false, true]]
|
|
3146
3330
|
];
|
|
3331
|
+
var SHAKER_SIXTEENTH_CURVE = [0.75, 0.45, 0.6, 0.45];
|
|
3332
|
+
var SHAKER_EIGHTH_CURVE = [0.75, 0.55];
|
|
3147
3333
|
function getPercussionConfig(mood, section) {
|
|
3148
3334
|
const row = _nullishCoalesce(PERC_TABLE[mood], () => ( PERC_TABLE[1 /* Standard */]));
|
|
3149
|
-
const act = _nullishCoalesce(_optionalChain([row, 'optionalAccess',
|
|
3335
|
+
const act = _nullishCoalesce(_optionalChain([row, 'optionalAccess', _40 => _40[sectionIndex(section)]]), () => ( F));
|
|
3150
3336
|
return {
|
|
3151
3337
|
tambourine: act[0],
|
|
3152
3338
|
shaker: act[1],
|
|
@@ -3168,10 +3354,11 @@ function generateAuxPercussionForBar(track, barStart, config, role, densityMult,
|
|
|
3168
3354
|
if (config.shaker) {
|
|
3169
3355
|
const use16th = config.shaker16th && bpm < HH_16TH_BPM_THRESHOLD && sustainsStrokes(SIXTEENTH, bpm, sec.difficulty);
|
|
3170
3356
|
if (use16th) {
|
|
3171
|
-
const velCurve =
|
|
3357
|
+
const velCurve = SHAKER_SIXTEENTH_CURVE;
|
|
3172
3358
|
for (let beat = 0; beat < barBeats; beat += 1) {
|
|
3173
3359
|
for (let sub = 0; sub < 4; sub += 1) {
|
|
3174
|
-
|
|
3360
|
+
const entry = sub % 2 === 1 ? draw.at("shaker16", barStart, beat, sub) : Number.NEGATIVE_INFINITY;
|
|
3361
|
+
if (!(entry < sec.rhythmic)) {
|
|
3175
3362
|
continue;
|
|
3176
3363
|
}
|
|
3177
3364
|
const raw = 80 * (_nullishCoalesce(velCurve[sub], () => ( 0.5))) * densityMult * draw.float(0.9, 1.1, "shaker", barStart, beat, sub);
|
|
@@ -3179,12 +3366,14 @@ function generateAuxPercussionForBar(track, barStart, config, role, densityMult,
|
|
|
3179
3366
|
GM.SHAKER,
|
|
3180
3367
|
swing16(barStart + beat + sub * SIXTEENTH, sec, swingAmount),
|
|
3181
3368
|
SIXTEENTH,
|
|
3182
|
-
Math.max(25, Math.min(85, raw))
|
|
3369
|
+
Math.max(25, Math.min(85, raw)),
|
|
3370
|
+
void 0,
|
|
3371
|
+
entry
|
|
3183
3372
|
);
|
|
3184
3373
|
}
|
|
3185
3374
|
}
|
|
3186
3375
|
} else {
|
|
3187
|
-
const velCurve =
|
|
3376
|
+
const velCurve = SHAKER_EIGHTH_CURVE;
|
|
3188
3377
|
for (let beat = 0; beat < barBeats; beat += 1) {
|
|
3189
3378
|
for (let sub = 0; sub < 2; sub += 1) {
|
|
3190
3379
|
const raw = 80 * (_nullishCoalesce(velCurve[sub], () => ( 0.6))) * densityMult * draw.float(0.9, 1.1, "shaker", barStart, beat, sub);
|
|
@@ -3251,12 +3440,12 @@ var KIT_ARTICULATIONS = Object.freeze([
|
|
|
3251
3440
|
var DRUM_KIT = Object.freeze({
|
|
3252
3441
|
kind: "percussion",
|
|
3253
3442
|
name: "drum kit",
|
|
3254
|
-
limbs:
|
|
3443
|
+
limbs: _chunkWOMCXN2Wcjs.LIMBS,
|
|
3255
3444
|
reach: deepFreeze(reachByNote()),
|
|
3256
3445
|
overdub: deepFreeze(OVERDUB_VOICES.map((voice) => DRUM_NOTES[voice])),
|
|
3257
3446
|
articulations: KIT_ARTICULATIONS,
|
|
3258
3447
|
// One stroke per limb, and one more per voice dubbed over them.
|
|
3259
|
-
polyphony:
|
|
3448
|
+
polyphony: _chunkWOMCXN2Wcjs.LIMBS.length + OVERDUB_VOICES.length
|
|
3260
3449
|
});
|
|
3261
3450
|
|
|
3262
3451
|
// src/generate/drums/vocabulary.ts
|
|
@@ -3267,8 +3456,8 @@ function isDrumPattern(material) {
|
|
|
3267
3456
|
function assertDrumPattern(material, label) {
|
|
3268
3457
|
material.strokes.forEach((stroke, index) => {
|
|
3269
3458
|
if (typeof stroke !== "object" || stroke === null || typeof stroke.voice !== "string" || drumNoteOf(stroke.voice) === void 0) {
|
|
3270
|
-
throw new (0,
|
|
3271
|
-
`${label} strokes[${index}].voice must name a drum voice; received ${
|
|
3459
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
3460
|
+
`${label} strokes[${index}].voice must name a drum voice; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, _optionalChain([stroke, 'optionalAccess', _41 => _41.voice]))}`
|
|
3272
3461
|
);
|
|
3273
3462
|
}
|
|
3274
3463
|
});
|
|
@@ -3460,21 +3649,22 @@ var DEFAULT_VELOCITY = 100;
|
|
|
3460
3649
|
var DEFAULT_BPM2 = 120;
|
|
3461
3650
|
var MAX_STROKES_PER_BAR = 64;
|
|
3462
3651
|
function placeDrumPattern(opts) {
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
const genre =
|
|
3467
|
-
const section = opts.section === void 0 ? void 0 :
|
|
3468
|
-
const ts =
|
|
3652
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "drum pattern options");
|
|
3653
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, opts.bars, "drum pattern bars");
|
|
3654
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, opts.bars * MAX_STROKES_PER_BAR, "drum pattern hits", opts.budget);
|
|
3655
|
+
const genre = _chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.genre, GENRES, "drum pattern genre");
|
|
3656
|
+
const section = opts.section === void 0 ? void 0 : _chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.section, PUBLIC_SECTIONS, "drum pattern section");
|
|
3657
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( FOUR_FOUR2)), "ts"));
|
|
3469
3658
|
if (opts.velocity !== void 0) {
|
|
3470
|
-
|
|
3659
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, opts.velocity, 1, 127, "drum pattern velocity");
|
|
3471
3660
|
}
|
|
3472
|
-
const feel = opts.feel === void 0 ? "straight" :
|
|
3661
|
+
const feel = opts.feel === void 0 ? "straight" : _chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.feel, DRUM_FEELS, "feel");
|
|
3662
|
+
const rate = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.rate, () => ( "straight")), FIGURE_RATES, "rate");
|
|
3473
3663
|
const resolved = resolveContext(opts.ctx);
|
|
3474
3664
|
const bpm = _nullishCoalesce(resolved.bpm, () => ( DEFAULT_BPM2));
|
|
3475
3665
|
const draw = resolved.part("drums");
|
|
3476
3666
|
const baseVelocity = _nullishCoalesce(opts.velocity, () => ( DEFAULT_VELOCITY));
|
|
3477
|
-
const barBeats =
|
|
3667
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts);
|
|
3478
3668
|
const kit = resolved.instrument("drums");
|
|
3479
3669
|
const swing = effectiveSwing(feel, feelSwingAmount(feel));
|
|
3480
3670
|
const supplied = vocabularyOfKind(resolved.vocabulary, isDrumPattern);
|
|
@@ -3483,8 +3673,8 @@ function placeDrumPattern(opts) {
|
|
|
3483
3673
|
});
|
|
3484
3674
|
const dictionary = mergeVocabulary(DRUM_PATTERNS, supplied);
|
|
3485
3675
|
if (selectVocabulary(dictionary, { ts }).length === 0) {
|
|
3486
|
-
throw new (0,
|
|
3487
|
-
`drum pattern ts names a meter no figure is written in: ${
|
|
3676
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
3677
|
+
`drum pattern ts names a meter no figure is written in: ${_chunkS3QELJUEcjs.formatTimeSignature.call(void 0, ts)}. The built-in figures are written in 4/4; supply vocabulary in another meter through the context.`
|
|
3488
3678
|
);
|
|
3489
3679
|
}
|
|
3490
3680
|
const track = new HitList();
|
|
@@ -3515,7 +3705,7 @@ function placeDrumPattern(opts) {
|
|
|
3515
3705
|
...resolved.rhythmic === void 0 ? {} : { rhythmic: resolved.rhythmic },
|
|
3516
3706
|
...resolved.ornament === void 0 ? {} : { ornament: resolved.ornament },
|
|
3517
3707
|
isOrnament: (stroke) => stroke.articulation === "ghost",
|
|
3518
|
-
rate
|
|
3708
|
+
rate,
|
|
3519
3709
|
spanSteps: entry.material.steps,
|
|
3520
3710
|
// The dials rank the figure's positions against the bar it is written
|
|
3521
3711
|
// in, which is the bar this call is placing it in.
|
|
@@ -3549,26 +3739,26 @@ function placeDrumPattern(opts) {
|
|
|
3549
3739
|
}
|
|
3550
3740
|
}
|
|
3551
3741
|
const endBeat = opts.bars * barBeats;
|
|
3552
|
-
return track.hits.filter((h) => h.startBeat < endBeat && (kit === void 0 ||
|
|
3742
|
+
return track.hits.filter((h) => h.startBeat < endBeat && (kit === void 0 || _chunkWOMCXN2Wcjs.canSound.call(void 0, kit, h.pitch))).sort((a, b) => a.startBeat - b.startBeat || a.pitch - b.pitch);
|
|
3553
3743
|
}
|
|
3554
3744
|
|
|
3555
3745
|
// src/generate/drums/index.ts
|
|
3556
3746
|
var MAX_HITS_PER_BAR = 128;
|
|
3557
3747
|
var DEFAULT_BPM3 = 120;
|
|
3558
3748
|
function generateDrums(opts) {
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3749
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "drum options");
|
|
3750
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, opts.bars, "drum bars");
|
|
3751
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, opts.bars * MAX_HITS_PER_BAR, "drum hits", opts.budget);
|
|
3562
3752
|
if (opts.euclideanKick) {
|
|
3563
3753
|
const steps = _nullishCoalesce(opts.euclideanKick.steps, () => ( 16));
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3754
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, steps, "euclidean steps", 1, 16);
|
|
3755
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, opts.euclideanKick.pulses, "euclidean pulses");
|
|
3756
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, _nullishCoalesce(opts.euclideanKick.rotation, () => ( 0)), "euclidean rotation");
|
|
3567
3757
|
}
|
|
3568
|
-
const publicStyle =
|
|
3569
|
-
const publicSection =
|
|
3758
|
+
const publicStyle = _chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.style, GROOVE_STYLES, "drum style");
|
|
3759
|
+
const publicSection = _chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.section, PUBLIC_SECTIONS, "drum section");
|
|
3570
3760
|
if (opts.nextSection !== void 0) {
|
|
3571
|
-
|
|
3761
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.nextSection, PUBLIC_SECTIONS, "drum nextSection");
|
|
3572
3762
|
}
|
|
3573
3763
|
const track = new HitList();
|
|
3574
3764
|
const resolved = resolveContext(opts.ctx);
|
|
@@ -3579,18 +3769,18 @@ function generateDrums(opts) {
|
|
|
3579
3769
|
const difficulty = resolved.difficulty;
|
|
3580
3770
|
const mapping = mapStyle(publicStyle);
|
|
3581
3771
|
const style = mapping.style;
|
|
3582
|
-
const feel = opts.feel === void 0 ? mapping.feel :
|
|
3583
|
-
const role = opts.role === void 0 ? "full" :
|
|
3584
|
-
const meters =
|
|
3772
|
+
const feel = opts.feel === void 0 ? mapping.feel : _chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.feel, DRUM_FEELS, "drum feel");
|
|
3773
|
+
const role = opts.role === void 0 ? "full" : _chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.role, DRUM_ROLES, "drum role");
|
|
3774
|
+
const meters = _chunkS3QELJUEcjs.resolveMeters.call(void 0, { ts: opts.ts }, "ts");
|
|
3585
3775
|
for (const change of meters) {
|
|
3586
3776
|
if (change.ts.numerator !== 4 || change.ts.denominator !== 4) {
|
|
3587
|
-
throw new (0,
|
|
3777
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
3588
3778
|
`drum time signature must be 4/4 throughout; received ${change.ts.numerator}/${change.ts.denominator} at beat ${change.startBeat}`
|
|
3589
3779
|
);
|
|
3590
3780
|
}
|
|
3591
3781
|
}
|
|
3592
|
-
const ts =
|
|
3593
|
-
const barBeats =
|
|
3782
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, meters);
|
|
3783
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts);
|
|
3594
3784
|
const playMainVoices = role !== "fxOnly";
|
|
3595
3785
|
const section = mapSection(publicSection);
|
|
3596
3786
|
const swingAmount = feelSwingAmount(feel);
|
|
@@ -3602,6 +3792,7 @@ function generateDrums(opts) {
|
|
|
3602
3792
|
densityMult,
|
|
3603
3793
|
rhythmic,
|
|
3604
3794
|
ornament: ornamentDial,
|
|
3795
|
+
ornamentFollowsRhythmic: resolved.ornament === void 0,
|
|
3605
3796
|
difficulty,
|
|
3606
3797
|
ghostBoost: mapping.ghostBoost,
|
|
3607
3798
|
useRide: shouldUseRideForSection(section, style),
|
|
@@ -3617,13 +3808,18 @@ function generateDrums(opts) {
|
|
|
3617
3808
|
const percMood = percMoodCategory(style);
|
|
3618
3809
|
const nextSection = opts.nextSection ? mapSection(opts.nextSection) : section;
|
|
3619
3810
|
const nextEnergy = sectionEnergy(nextSection);
|
|
3620
|
-
const
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
);
|
|
3811
|
+
const suppliedFills = vocabularyOfKind(resolved.vocabulary, isFillArchetype);
|
|
3812
|
+
suppliedFills.forEach((entry, index) => {
|
|
3813
|
+
assertFillArchetype(entry.material, `drum fill vocabulary[${index}]`);
|
|
3814
|
+
});
|
|
3815
|
+
const callerFillEntries = selectVocabulary(suppliedFills, {
|
|
3816
|
+
section: publicSection,
|
|
3817
|
+
bpm,
|
|
3818
|
+
difficulty
|
|
3819
|
+
});
|
|
3624
3820
|
const callerFills = new Map(callerFillEntries.map((entry) => [entry.id, entry.material]));
|
|
3625
3821
|
const callerFillIds = callerFillEntries.map((entry) => entry.id);
|
|
3626
|
-
const euclidSteps = _nullishCoalesce(_optionalChain([opts, 'access',
|
|
3822
|
+
const euclidSteps = _nullishCoalesce(_optionalChain([opts, 'access', _42 => _42.euclideanKick, 'optionalAccess', _43 => _43.steps]), () => ( 16));
|
|
3627
3823
|
const euclidKick = opts.euclideanKick ? euclideanRhythm(opts.euclideanKick.pulses, euclidSteps, _nullishCoalesce(opts.euclideanKick.rotation, () => ( 0))) : void 0;
|
|
3628
3824
|
const reuseSectionKick = (section === "b" || section === "chorus") && style !== "sparse";
|
|
3629
3825
|
let sectionKick;
|
|
@@ -3631,7 +3827,7 @@ function generateDrums(opts) {
|
|
|
3631
3827
|
for (let bar2 = 0; bar2 < opts.bars; bar2 += 1) {
|
|
3632
3828
|
const barStart = bar2 * barBeats;
|
|
3633
3829
|
const isLastBar = bar2 === opts.bars - 1;
|
|
3634
|
-
const
|
|
3830
|
+
const hiHat = getHiHatBar(section, style, rhythmic, bpm, draw, difficulty, bar2);
|
|
3635
3831
|
if (bar2 === 0 && section === "chorus") {
|
|
3636
3832
|
track.add(GM.CRASH, barStart, 0.5, 100 * densityMult);
|
|
3637
3833
|
}
|
|
@@ -3643,10 +3839,10 @@ function generateDrums(opts) {
|
|
|
3643
3839
|
}
|
|
3644
3840
|
let kick;
|
|
3645
3841
|
if (!euclidKick && reuseSectionKick) {
|
|
3646
|
-
sectionKick ??=
|
|
3842
|
+
sectionKick ??= getKickEntries(section, style, 0, draw, rhythmic);
|
|
3647
3843
|
kick = sectionKick;
|
|
3648
3844
|
} else if (!euclidKick) {
|
|
3649
|
-
kick =
|
|
3845
|
+
kick = getKickEntries(section, style, bar2, draw, rhythmic);
|
|
3650
3846
|
}
|
|
3651
3847
|
const inLift = isInPreChorusLift(section, bar2, opts.bars, nextSection === "chorus");
|
|
3652
3848
|
let currentFill = FILL_ARCHETYPES.snareRoll;
|
|
@@ -3702,7 +3898,8 @@ function generateDrums(opts) {
|
|
|
3702
3898
|
swingAmount,
|
|
3703
3899
|
barHasOpenHh,
|
|
3704
3900
|
openHhBeat: openHhBeatIndex,
|
|
3705
|
-
hhLevel,
|
|
3901
|
+
hhLevel: hiHat.level,
|
|
3902
|
+
hhEntries: hiHat.entries,
|
|
3706
3903
|
draw
|
|
3707
3904
|
};
|
|
3708
3905
|
if (playMainVoices) {
|
|
@@ -3763,27 +3960,47 @@ function generateDrums(opts) {
|
|
|
3763
3960
|
const endBeat = opts.bars * barBeats;
|
|
3764
3961
|
const kit = resolved.instrument("drums");
|
|
3765
3962
|
const written = track.hits.filter((hit2) => hit2.startBeat < endBeat && playableOn(kit, hit2.pitch)).sort((a, b) => a.startBeat - b.startBeat || a.pitch - b.pitch);
|
|
3766
|
-
return underCeiling(written, bpm, difficulty, exemptOnsets);
|
|
3963
|
+
return underCeiling(written, bpm, difficulty, exemptOnsets, track);
|
|
3767
3964
|
}
|
|
3768
|
-
function underCeiling(hits, bpm, difficulty, exempt) {
|
|
3965
|
+
function underCeiling(hits, bpm, difficulty, exempt, track) {
|
|
3769
3966
|
if (difficulty === void 0) {
|
|
3770
3967
|
return [...hits];
|
|
3771
3968
|
}
|
|
3772
|
-
const
|
|
3773
|
-
const
|
|
3774
|
-
|
|
3775
|
-
const
|
|
3776
|
-
|
|
3969
|
+
const entries = hits.map((hit2) => track.entryOf(hit2.pitch, hit2.startBeat));
|
|
3970
|
+
const order = hits.map((_, index) => index).sort((a, b) => {
|
|
3971
|
+
const left = entries[a];
|
|
3972
|
+
const right = entries[b];
|
|
3973
|
+
return left < right ? -1 : left > right ? 1 : a - b;
|
|
3974
|
+
});
|
|
3975
|
+
const keptBeats = /* @__PURE__ */ new Map();
|
|
3976
|
+
const kept = hits.map(() => false);
|
|
3977
|
+
for (const index of order) {
|
|
3978
|
+
const hit2 = hits[index];
|
|
3979
|
+
const beats = _nullishCoalesce(keptBeats.get(hit2.pitch), () => ( []));
|
|
3980
|
+
let at2 = 0;
|
|
3981
|
+
let end = beats.length;
|
|
3982
|
+
while (at2 < end) {
|
|
3983
|
+
const mid = at2 + end >>> 1;
|
|
3984
|
+
if (beats[mid] > hit2.startBeat) {
|
|
3985
|
+
end = mid;
|
|
3986
|
+
} else {
|
|
3987
|
+
at2 = mid + 1;
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
const previous = beats[at2 - 1];
|
|
3991
|
+
const next = beats[at2];
|
|
3992
|
+
const reachable = exempt.has(onsetKey(hit2.pitch, hit2.startBeat)) || (previous === void 0 || sustainsStrokes(hit2.startBeat - previous, bpm, difficulty)) && (next === void 0 || sustainsStrokes(next - hit2.startBeat, bpm, difficulty));
|
|
3777
3993
|
if (!reachable) {
|
|
3778
3994
|
continue;
|
|
3779
3995
|
}
|
|
3780
|
-
kept
|
|
3781
|
-
|
|
3996
|
+
kept[index] = true;
|
|
3997
|
+
beats.splice(at2, 0, hit2.startBeat);
|
|
3998
|
+
keptBeats.set(hit2.pitch, beats);
|
|
3782
3999
|
}
|
|
3783
|
-
return kept;
|
|
4000
|
+
return hits.filter((_, index) => kept[index]);
|
|
3784
4001
|
}
|
|
3785
4002
|
function playableOn(kit, pitch) {
|
|
3786
|
-
return kit === void 0 ||
|
|
4003
|
+
return kit === void 0 || _chunkWOMCXN2Wcjs.canSound.call(void 0, kit, pitch);
|
|
3787
4004
|
}
|
|
3788
4005
|
|
|
3789
4006
|
// src/generate/groove/index.ts
|
|
@@ -3798,24 +4015,24 @@ var MAX_METRIC_WEIGHT = 3;
|
|
|
3798
4015
|
var MIN_VELOCITY = 1;
|
|
3799
4016
|
var MAX_VELOCITY = 127;
|
|
3800
4017
|
function humanize(events, opts = {}) {
|
|
3801
|
-
const asked =
|
|
3802
|
-
const
|
|
3803
|
-
|
|
3804
|
-
const sounding2 =
|
|
4018
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
4019
|
+
const meter = _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(asked.ts, () => ( DEFAULT_TS3)), "ts");
|
|
4020
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, events, "humanize events", { allowNonPositiveDuration: true });
|
|
4021
|
+
const sounding2 = _chunkS3QELJUEcjs.dropSilentNotes.call(void 0, events);
|
|
3805
4022
|
const timing = _nullishCoalesce(asked.timing, () => ( DEFAULT_TIMING));
|
|
3806
4023
|
const velocityJitter = _nullishCoalesce(asked.velocity, () => ( DEFAULT_VELOCITY_JITTER));
|
|
3807
4024
|
const accent2 = _nullishCoalesce(asked.accent, () => ( DEFAULT_ACCENT));
|
|
3808
4025
|
const baseVelocity = _nullishCoalesce(asked.baseVelocity, () => ( DEFAULT_BASE_VELOCITY));
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
4026
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, timing, 0, Number.MAX_SAFE_INTEGER, "humanize timing");
|
|
4027
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, velocityJitter, 0, 127, "humanize velocity jitter");
|
|
4028
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, accent2, 0, 127, "humanize accent");
|
|
4029
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, baseVelocity, 0, 127, "humanize base velocity");
|
|
3813
4030
|
const ctx = resolveContext(asked.ctx);
|
|
3814
4031
|
const draw = ctx.part(_nullishCoalesce(asked.part, () => ( DEFAULT_PART)));
|
|
3815
4032
|
return sounding2.map((event) => {
|
|
3816
4033
|
const timingOffset = draw.float(-timing, timing, "timing", event.startBeat, event.pitch);
|
|
3817
4034
|
const startBeat = event.startBeat + timingOffset;
|
|
3818
|
-
const weight =
|
|
4035
|
+
const weight = _chunkS3QELJUEcjs.metricWeight.call(void 0, event.startBeat, meter);
|
|
3819
4036
|
const accentBoost = weight / MAX_METRIC_WEIGHT * accent2;
|
|
3820
4037
|
const velocityOffset = draw.float(
|
|
3821
4038
|
-velocityJitter,
|
|
@@ -3829,6 +4046,21 @@ function humanize(events, opts = {}) {
|
|
|
3829
4046
|
return { ...event, startBeat, velocity };
|
|
3830
4047
|
});
|
|
3831
4048
|
}
|
|
4049
|
+
function grooveSignature(ts) {
|
|
4050
|
+
const meter = _chunkS3QELJUEcjs.toMeterData.call(void 0, ts, "ts");
|
|
4051
|
+
if (!Array.isArray(meter)) {
|
|
4052
|
+
return meter;
|
|
4053
|
+
}
|
|
4054
|
+
const opening = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, meter);
|
|
4055
|
+
for (const change of meter) {
|
|
4056
|
+
if (change.ts.numerator !== opening.numerator || change.ts.denominator !== opening.denominator) {
|
|
4057
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4058
|
+
`groove time signature must be one signature throughout; received ${change.ts.numerator}/${change.ts.denominator} at beat ${change.startBeat} in a meter that is ${opening.numerator}/${opening.denominator} at beat 0`
|
|
4059
|
+
);
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
return opening;
|
|
4063
|
+
}
|
|
3832
4064
|
function quantizeToGrid(beat, barBeats, subdivision, slotsPerBar) {
|
|
3833
4065
|
const barIndex = Math.floor(beat / barBeats);
|
|
3834
4066
|
const modBeat = beat - barIndex * barBeats;
|
|
@@ -3844,18 +4076,18 @@ function quantizeToGrid(beat, barBeats, subdivision, slotsPerBar) {
|
|
|
3844
4076
|
};
|
|
3845
4077
|
}
|
|
3846
4078
|
function extractGrooveTemplate(events, ts, subdivision = DEFAULT_GROOVE_SUBDIVISION) {
|
|
3847
|
-
const meter =
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
const barBeats =
|
|
4079
|
+
const meter = grooveSignature(ts);
|
|
4080
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, events, "groove source events", { allowNonPositiveDuration: true });
|
|
4081
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, subdivision, "groove subdivision");
|
|
4082
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, meter);
|
|
3851
4083
|
const slotsPerBar = Math.ceil(barBeats * subdivision);
|
|
3852
|
-
|
|
3853
|
-
|
|
4084
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, slotsPerBar, "groove template slots");
|
|
4085
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, slotsPerBar, "groove template slots");
|
|
3854
4086
|
const offsetSums = new Array(slotsPerBar).fill(0);
|
|
3855
4087
|
const velocitySums = new Array(slotsPerBar).fill(0);
|
|
3856
4088
|
const counts = new Array(slotsPerBar).fill(0);
|
|
3857
4089
|
const velocityCounts = new Array(slotsPerBar).fill(0);
|
|
3858
|
-
for (const event of
|
|
4090
|
+
for (const event of _chunkS3QELJUEcjs.dropSilentNotes.call(void 0, events)) {
|
|
3859
4091
|
const { quantizedBeat, slotIndex } = quantizeToGrid(
|
|
3860
4092
|
event.startBeat,
|
|
3861
4093
|
barBeats,
|
|
@@ -3885,24 +4117,24 @@ function extractGrooveTemplate(events, ts, subdivision = DEFAULT_GROOVE_SUBDIVIS
|
|
|
3885
4117
|
return { subdivision, slotsPerBar, slots, ts: meter };
|
|
3886
4118
|
}
|
|
3887
4119
|
function applyGrooveTemplate(events, template, ts) {
|
|
3888
|
-
const meter =
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
4120
|
+
const meter = grooveSignature(ts);
|
|
4121
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, events, "groove target events", { allowNonPositiveDuration: true });
|
|
4122
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, template.subdivision, "template subdivision");
|
|
4123
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, template.slotsPerBar, "template slotsPerBar");
|
|
4124
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, template.slots.length, "template slots");
|
|
3893
4125
|
if (template.slots.length !== template.slotsPerBar) {
|
|
3894
|
-
throw new (0,
|
|
4126
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("template slots length must equal slotsPerBar");
|
|
3895
4127
|
}
|
|
3896
4128
|
if (template.ts && (template.ts.numerator !== meter.numerator || template.ts.denominator !== meter.denominator)) {
|
|
3897
|
-
throw new (0,
|
|
3898
|
-
`Groove template meter ${
|
|
4129
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4130
|
+
`Groove template meter ${_chunkS3QELJUEcjs.formatTimeSignature.call(void 0, template.ts)} does not match apply-time meter ${_chunkS3QELJUEcjs.formatTimeSignature.call(void 0, meter)}`
|
|
3899
4131
|
);
|
|
3900
4132
|
}
|
|
3901
|
-
const barBeats =
|
|
4133
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, meter);
|
|
3902
4134
|
const expectedSlots = Math.ceil(barBeats * template.subdivision);
|
|
3903
4135
|
if (template.slotsPerBar !== expectedSlots) {
|
|
3904
|
-
throw new (0,
|
|
3905
|
-
`Groove template slotsPerBar ${template.slotsPerBar} does not match ${expectedSlots} slots per bar of ${
|
|
4136
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4137
|
+
`Groove template slotsPerBar ${template.slotsPerBar} does not match ${expectedSlots} slots per bar of ${_chunkS3QELJUEcjs.formatTimeSignature.call(void 0, meter)} at subdivision ${template.subdivision}`
|
|
3906
4138
|
);
|
|
3907
4139
|
}
|
|
3908
4140
|
for (let index = 0; index < template.slots.length; index += 1) {
|
|
@@ -3910,12 +4142,12 @@ function applyGrooveTemplate(events, template, ts) {
|
|
|
3910
4142
|
if (slot === void 0) {
|
|
3911
4143
|
continue;
|
|
3912
4144
|
}
|
|
3913
|
-
|
|
4145
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, slot.timingOffset, `template slots[${index}].timingOffset`);
|
|
3914
4146
|
if (slot.velocity !== null && slot.velocity !== void 0) {
|
|
3915
|
-
|
|
4147
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, slot.velocity, 0, 127, `template slots[${index}].velocity`);
|
|
3916
4148
|
}
|
|
3917
4149
|
}
|
|
3918
|
-
return
|
|
4150
|
+
return _chunkS3QELJUEcjs.dropSilentNotes.call(void 0, events).map((event) => {
|
|
3919
4151
|
const { quantizedBeat, slotIndex } = quantizeToGrid(
|
|
3920
4152
|
event.startBeat,
|
|
3921
4153
|
barBeats,
|
|
@@ -3923,7 +4155,7 @@ function applyGrooveTemplate(events, template, ts) {
|
|
|
3923
4155
|
template.slotsPerBar
|
|
3924
4156
|
);
|
|
3925
4157
|
const slot = template.slots[slotIndex];
|
|
3926
|
-
const startBeat = quantizedBeat + (_nullishCoalesce(_optionalChain([slot, 'optionalAccess',
|
|
4158
|
+
const startBeat = quantizedBeat + (_nullishCoalesce(_optionalChain([slot, 'optionalAccess', _44 => _44.timingOffset]), () => ( 0)));
|
|
3927
4159
|
const velocity = slot && slot.velocity !== null && slot.velocity !== void 0 ? Math.round(slot.velocity) : event.velocity;
|
|
3928
4160
|
return { ...event, startBeat, velocity };
|
|
3929
4161
|
});
|
|
@@ -3932,7 +4164,7 @@ function applyGrooveTemplate(events, template, ts) {
|
|
|
3932
4164
|
// src/generate/harmonize/nct.ts
|
|
3933
4165
|
function snapToPulse(beat, pulse2) {
|
|
3934
4166
|
const snapped = Math.round(beat / pulse2) * pulse2;
|
|
3935
|
-
return Math.abs(snapped - beat) <=
|
|
4167
|
+
return Math.abs(snapped - beat) <= _chunkLQZQDBCDcjs.HUMANIZE_ADJACENCY ? snapped : beat;
|
|
3936
4168
|
}
|
|
3937
4169
|
var STEP_SEMITONES = 2;
|
|
3938
4170
|
function isStep(a, b) {
|
|
@@ -3946,29 +4178,41 @@ function sameDirection(prev, note2, next) {
|
|
|
3946
4178
|
return prev !== note2 && next !== note2 && note2 - prev > 0 === next - note2 > 0;
|
|
3947
4179
|
}
|
|
3948
4180
|
function classifyMelodyTones(melody, ts) {
|
|
3949
|
-
const meter =
|
|
3950
|
-
|
|
3951
|
-
const pulse2 =
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
4181
|
+
const meter = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, ts, "ts"));
|
|
4182
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, melody, "melody notes", { allowNonPositiveDuration: true });
|
|
4183
|
+
const pulse2 = _chunkS3QELJUEcjs.pulseBeats.call(void 0, meter);
|
|
4184
|
+
const sounding2 = new Set(_chunkKMYGRFZ6cjs.soundingIndices.call(void 0, melody));
|
|
4185
|
+
const line = _chunkKMYGRFZ6cjs.canonicalNoteOrder.call(void 0, melody).filter((index) => sounding2.has(index));
|
|
4186
|
+
const roles = melody.map(() => "structural");
|
|
4187
|
+
line.forEach((index, position) => {
|
|
4188
|
+
const before = line[position - 1];
|
|
4189
|
+
const after = line[position + 1];
|
|
4190
|
+
roles[index] = roleOfNote(
|
|
4191
|
+
before === void 0 ? void 0 : melody[before],
|
|
4192
|
+
melody[index],
|
|
4193
|
+
after === void 0 ? void 0 : melody[after],
|
|
4194
|
+
meter,
|
|
4195
|
+
pulse2
|
|
4196
|
+
);
|
|
3955
4197
|
});
|
|
4198
|
+
return roles.map((role, index) => ({
|
|
4199
|
+
noteIndex: index,
|
|
4200
|
+
role,
|
|
4201
|
+
ornamental: role !== "structural"
|
|
4202
|
+
}));
|
|
3956
4203
|
}
|
|
3957
|
-
function roleOfNote(
|
|
3958
|
-
const note2 = melody[index];
|
|
3959
|
-
const prev = melody[index - 1];
|
|
3960
|
-
const next = melody[index + 1];
|
|
4204
|
+
function roleOfNote(prev, note2, next, ts, pulse2) {
|
|
3961
4205
|
if (!note2 || !prev || !next) {
|
|
3962
4206
|
return "structural";
|
|
3963
4207
|
}
|
|
3964
4208
|
const intoNote = Math.abs(prev.startBeat + prev.durationBeat - note2.startBeat);
|
|
3965
4209
|
const outOfNote = Math.abs(note2.startBeat + note2.durationBeat - next.startBeat);
|
|
3966
|
-
if (intoNote >
|
|
4210
|
+
if (intoNote > _chunkLQZQDBCDcjs.HUMANIZE_ADJACENCY || outOfNote > _chunkLQZQDBCDcjs.HUMANIZE_ADJACENCY) {
|
|
3967
4211
|
return "structural";
|
|
3968
4212
|
}
|
|
3969
|
-
const weight =
|
|
3970
|
-
const weightPrev =
|
|
3971
|
-
const weightNext =
|
|
4213
|
+
const weight = _chunkS3QELJUEcjs.metricWeight.call(void 0, snapToPulse(note2.startBeat, pulse2), ts);
|
|
4214
|
+
const weightPrev = _chunkS3QELJUEcjs.metricWeight.call(void 0, snapToPulse(prev.startBeat, pulse2), ts);
|
|
4215
|
+
const weightNext = _chunkS3QELJUEcjs.metricWeight.call(void 0, snapToPulse(next.startBeat, pulse2), ts);
|
|
3972
4216
|
const subordinate = weight <= weightPrev && weight <= weightNext && note2.durationBeat <= prev.durationBeat && note2.durationBeat <= next.durationBeat;
|
|
3973
4217
|
const leaning = weight > weightPrev && weight >= weightNext;
|
|
3974
4218
|
if (leaning && prev.pitch === note2.pitch && note2.pitch - next.pitch >= 1 && isStep(note2.pitch, next.pitch)) {
|
|
@@ -4000,12 +4244,12 @@ var FALLBACK = {
|
|
|
4000
4244
|
quality: "maj",
|
|
4001
4245
|
secondaryDominant: false,
|
|
4002
4246
|
base: 0,
|
|
4003
|
-
pcs:
|
|
4247
|
+
pcs: _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, 0, "maj"))
|
|
4004
4248
|
};
|
|
4005
4249
|
function defaultHarmonicRhythm(ts) {
|
|
4006
|
-
const bar2 =
|
|
4250
|
+
const bar2 = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts);
|
|
4007
4251
|
const half = bar2 / 2;
|
|
4008
|
-
return half %
|
|
4252
|
+
return half % _chunkS3QELJUEcjs.pulseBeats.call(void 0, ts) === 0 ? half : bar2;
|
|
4009
4253
|
}
|
|
4010
4254
|
var DEFAULT_PLACEMENT = {
|
|
4011
4255
|
transposeSearch: false,
|
|
@@ -4013,25 +4257,23 @@ var DEFAULT_PLACEMENT = {
|
|
|
4013
4257
|
};
|
|
4014
4258
|
var DEFAULT_METER = { numerator: 4, denominator: 4 };
|
|
4015
4259
|
var TIE_BREAK_JITTER2 = 1e-6;
|
|
4016
|
-
function cadencesThroughRaisedSeventh(key) {
|
|
4017
|
-
return _chunkIFZDWIKMcjs.isMinorKey.call(void 0, key) && _chunk3R3QVKY5cjs.scaleSystemOf.call(void 0, key) === "common-practice";
|
|
4018
|
-
}
|
|
4019
4260
|
function isKeyTone(pitch, key) {
|
|
4020
|
-
return
|
|
4261
|
+
return _chunkYDGMWH43cjs.isScaleTone.call(void 0, pitch, key) || _chunkYDGMWH43cjs.cadencesThroughRaisedSeventh.call(void 0, key) && _chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch) === _chunkYDGMWH43cjs.leadingTonePcOf.call(void 0, key);
|
|
4021
4262
|
}
|
|
4022
4263
|
function inferKey(melody) {
|
|
4023
|
-
|
|
4264
|
+
const line = inOnsetOrder(melody);
|
|
4265
|
+
let best = _chunkYDGMWH43cjs.majorKey.call(void 0, 0);
|
|
4024
4266
|
let bestScore = Number.NEGATIVE_INFINITY;
|
|
4025
4267
|
const candidates = [];
|
|
4026
4268
|
for (let tonic = 0; tonic < 12; tonic += 1) {
|
|
4027
|
-
candidates.push(
|
|
4269
|
+
candidates.push(_chunkYDGMWH43cjs.majorKey.call(void 0, tonic), _chunkYDGMWH43cjs.minorKey.call(void 0, tonic));
|
|
4028
4270
|
}
|
|
4029
4271
|
for (const key of candidates) {
|
|
4030
|
-
const tonic =
|
|
4272
|
+
const tonic = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
4031
4273
|
let score = 0;
|
|
4032
|
-
for (const n of
|
|
4274
|
+
for (const n of line) {
|
|
4033
4275
|
const w = Math.max(0.25, n.durationBeat);
|
|
4034
|
-
const pc =
|
|
4276
|
+
const pc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, n.pitch);
|
|
4035
4277
|
if (isKeyTone(n.pitch, key)) {
|
|
4036
4278
|
score += w;
|
|
4037
4279
|
}
|
|
@@ -4046,6 +4288,12 @@ function inferKey(melody) {
|
|
|
4046
4288
|
}
|
|
4047
4289
|
return best;
|
|
4048
4290
|
}
|
|
4291
|
+
function inOnsetOrder(melody) {
|
|
4292
|
+
return _chunkKMYGRFZ6cjs.canonicalNoteOrder.call(void 0, melody).flatMap((index) => {
|
|
4293
|
+
const note2 = melody[index];
|
|
4294
|
+
return note2 === void 0 ? [] : [note2];
|
|
4295
|
+
});
|
|
4296
|
+
}
|
|
4049
4297
|
|
|
4050
4298
|
// src/generate/harmonize/cost.ts
|
|
4051
4299
|
var NON_CHORD_TONE_STRONG = 4;
|
|
@@ -4066,7 +4314,7 @@ function emissionCost(seg, cand, melody, key) {
|
|
|
4066
4314
|
let cost = cand.base * seg.weight;
|
|
4067
4315
|
for (const { index, weight, strong } of seg.costNotes) {
|
|
4068
4316
|
const note2 = melody[index];
|
|
4069
|
-
if (!note2 || pcs.includes(
|
|
4317
|
+
if (!note2 || pcs.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, note2.pitch))) {
|
|
4070
4318
|
continue;
|
|
4071
4319
|
}
|
|
4072
4320
|
cost += (strong ? NON_CHORD_TONE_STRONG : NON_CHORD_TONE_WEAK) * weight;
|
|
@@ -4105,7 +4353,7 @@ function phraseEndBonus(prev, cur, tonicPc, seg, melody) {
|
|
|
4105
4353
|
return 0;
|
|
4106
4354
|
}
|
|
4107
4355
|
const closing = melody[seg.closingIndex];
|
|
4108
|
-
if (!closing ||
|
|
4356
|
+
if (!closing || _chunkS3QELJUEcjs.pitchClassOf.call(void 0, closing.pitch) !== tonicPc) {
|
|
4109
4357
|
return 0;
|
|
4110
4358
|
}
|
|
4111
4359
|
const weight = Math.max(seg.weight, seg.beats);
|
|
@@ -4142,7 +4390,7 @@ function sameHarmony(a, b) {
|
|
|
4142
4390
|
return a.rootPc === b.rootPc && a.quality === b.quality;
|
|
4143
4391
|
}
|
|
4144
4392
|
function harmonizeOnce(melody, key, candidates, segments, jitter, phraseEnds, articulated) {
|
|
4145
|
-
const tonicPc =
|
|
4393
|
+
const tonicPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
4146
4394
|
const n = candidates.length;
|
|
4147
4395
|
const candAt = (i) => _nullishCoalesce(candidates[i], () => ( FALLBACK));
|
|
4148
4396
|
const seg0 = segments[0];
|
|
@@ -4204,13 +4452,13 @@ function gridBounds(segmentStart, hr, gridCount, ends) {
|
|
|
4204
4452
|
}
|
|
4205
4453
|
const last = segmentStart + gridCount * hr;
|
|
4206
4454
|
for (const end of ends) {
|
|
4207
|
-
if (end > segmentStart +
|
|
4455
|
+
if (end > segmentStart + _chunkS3QELJUEcjs.BEAT_EPS && end < last - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
4208
4456
|
bounds.push(end);
|
|
4209
4457
|
}
|
|
4210
4458
|
}
|
|
4211
4459
|
bounds.sort((a, b) => a - b);
|
|
4212
4460
|
return bounds.filter(
|
|
4213
|
-
(beat, index) => index === 0 || beat - (_nullishCoalesce(bounds[index - 1], () => ( beat))) >
|
|
4461
|
+
(beat, index) => index === 0 || beat - (_nullishCoalesce(bounds[index - 1], () => ( beat))) > _chunkS3QELJUEcjs.BEAT_EPS
|
|
4214
4462
|
);
|
|
4215
4463
|
}
|
|
4216
4464
|
function closingNoteIndices(spans, ends) {
|
|
@@ -4219,7 +4467,7 @@ function closingNoteIndices(spans, ends) {
|
|
|
4219
4467
|
let index = -1;
|
|
4220
4468
|
let start = Number.NEGATIVE_INFINITY;
|
|
4221
4469
|
for (const [i, span] of spans.entries()) {
|
|
4222
|
-
if (span.startBeat < end -
|
|
4470
|
+
if (span.startBeat < end - _chunkS3QELJUEcjs.BEAT_EPS && span.startBeat >= start) {
|
|
4223
4471
|
start = span.startBeat;
|
|
4224
4472
|
index = i;
|
|
4225
4473
|
}
|
|
@@ -4262,7 +4510,7 @@ function phraseEndSegments(segments, ends) {
|
|
|
4262
4510
|
for (const end of ends) {
|
|
4263
4511
|
let index = -1;
|
|
4264
4512
|
for (let s = 0; s < segments.length; s += 1) {
|
|
4265
|
-
if ((_nullishCoalesce(_optionalChain([segments, 'access',
|
|
4513
|
+
if ((_nullishCoalesce(_optionalChain([segments, 'access', _45 => _45[s], 'optionalAccess', _46 => _46.startBeat]), () => ( 0))) < end - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
4266
4514
|
index = s;
|
|
4267
4515
|
}
|
|
4268
4516
|
}
|
|
@@ -4279,13 +4527,13 @@ function buildSegments(spans, melody, ts, grid, phraseEnds, budget) {
|
|
|
4279
4527
|
const hr = grid.harmonicRhythm;
|
|
4280
4528
|
const segmentStart = Math.floor(melodyStart / hr) * hr;
|
|
4281
4529
|
const gridCount = Math.max(1, Math.ceil((melodyEnd - segmentStart) / hr));
|
|
4282
|
-
|
|
4530
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, gridCount, "harmonic segments", budget);
|
|
4283
4531
|
const innerEnds = phraseEnds.filter(
|
|
4284
|
-
(end) => end > segmentStart +
|
|
4532
|
+
(end) => end > segmentStart + _chunkS3QELJUEcjs.BEAT_EPS && end < melodyEnd - _chunkS3QELJUEcjs.BEAT_EPS
|
|
4285
4533
|
);
|
|
4286
4534
|
const bounds = gridBounds(segmentStart, hr, gridCount, innerEnds);
|
|
4287
4535
|
const segCount = bounds.length - 1;
|
|
4288
|
-
|
|
4536
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, segCount, "harmonic segments", budget);
|
|
4289
4537
|
const segments = Array.from({ length: segCount }, (_, s) => {
|
|
4290
4538
|
const startBeat = _nullishCoalesce(bounds[s], () => ( segmentStart));
|
|
4291
4539
|
const endBeat = _nullishCoalesce(bounds[s + 1], () => ( startBeat + hr));
|
|
@@ -4306,16 +4554,16 @@ function buildSegments(spans, melody, ts, grid, phraseEnds, budget) {
|
|
|
4306
4554
|
lastExclusive += 1;
|
|
4307
4555
|
}
|
|
4308
4556
|
memberships += Math.max(0, lastExclusive - first);
|
|
4309
|
-
|
|
4557
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, memberships, "note-to-segment memberships", budget);
|
|
4310
4558
|
for (let segment = first; segment < lastExclusive; segment += 1) {
|
|
4311
|
-
_optionalChain([segments, 'access',
|
|
4559
|
+
_optionalChain([segments, 'access', _47 => _47[segment], 'optionalAccess', _48 => _48.noteIndices, 'access', _49 => _49.push, 'call', _50 => _50(index)]);
|
|
4312
4560
|
}
|
|
4313
4561
|
}
|
|
4314
4562
|
const tones = classifyMelodyTones(melody, ts);
|
|
4315
4563
|
const phraseClosingNotes = closingNoteIndices(spans, innerEnds);
|
|
4316
4564
|
for (const segment of segments) {
|
|
4317
4565
|
const structural = segment.noteIndices.filter(
|
|
4318
|
-
(idx) => _optionalChain([tones, 'access',
|
|
4566
|
+
(idx) => _optionalChain([tones, 'access', _51 => _51[idx], 'optionalAccess', _52 => _52.ornamental]) !== true || phraseClosingNotes.has(idx)
|
|
4319
4567
|
);
|
|
4320
4568
|
const costIndices = structural.length > 0 ? structural : segment.noteIndices;
|
|
4321
4569
|
let closingStart = Number.NEGATIVE_INFINITY;
|
|
@@ -4330,7 +4578,7 @@ function buildSegments(spans, melody, ts, grid, phraseEnds, budget) {
|
|
|
4330
4578
|
continue;
|
|
4331
4579
|
}
|
|
4332
4580
|
const weight = Math.max(0.25, overlap);
|
|
4333
|
-
segment.costNotes.push({ index, weight, strong:
|
|
4581
|
+
segment.costNotes.push({ index, weight, strong: _chunkS3QELJUEcjs.isStrongBeat.call(void 0, overlapStart, ts) });
|
|
4334
4582
|
segment.weight += weight;
|
|
4335
4583
|
if (span.startBeat >= closingStart) {
|
|
4336
4584
|
closingStart = span.startBeat;
|
|
@@ -4342,17 +4590,25 @@ function buildSegments(spans, melody, ts, grid, phraseEnds, budget) {
|
|
|
4342
4590
|
}
|
|
4343
4591
|
|
|
4344
4592
|
// src/generate/harmonize/candidates.ts
|
|
4345
|
-
var ROOT_WEIGHT_BY_SEMITONE = [
|
|
4593
|
+
var ROOT_WEIGHT_BY_SEMITONE = [
|
|
4594
|
+
0,
|
|
4595
|
+
0.9,
|
|
4596
|
+
0.3,
|
|
4597
|
+
0.45,
|
|
4598
|
+
0.45,
|
|
4599
|
+
0.15,
|
|
4600
|
+
0.9,
|
|
4601
|
+
0.1,
|
|
4602
|
+
0.3,
|
|
4603
|
+
0.3,
|
|
4604
|
+
0.3,
|
|
4605
|
+
0.9
|
|
4606
|
+
];
|
|
4346
4607
|
var UNSTABLE_TRIAD = 0.9;
|
|
4347
|
-
var
|
|
4348
|
-
|
|
4349
|
-
"aug",
|
|
4350
|
-
"dim7",
|
|
4351
|
-
"m7b5",
|
|
4352
|
-
"aug7"
|
|
4353
|
-
]);
|
|
4608
|
+
var UNSTABLE_QUALITY_NAMES = ["dim", "aug", "dim7", "m7b5", "aug7"];
|
|
4609
|
+
var UNSTABLE_QUALITIES = new Set(UNSTABLE_QUALITY_NAMES);
|
|
4354
4610
|
function vocabularyBase(rootPc, quality, tonicPc) {
|
|
4355
|
-
const above = (
|
|
4611
|
+
const above = (_chunkS3QELJUEcjs.pitchClassOf.call(void 0, rootPc) - tonicPc + 12) % 12;
|
|
4356
4612
|
const root = _nullishCoalesce(ROOT_WEIGHT_BY_SEMITONE[above], () => ( UNSTABLE_TRIAD));
|
|
4357
4613
|
return UNSTABLE_QUALITIES.has(quality) ? Math.max(root, UNSTABLE_TRIAD) : root;
|
|
4358
4614
|
}
|
|
@@ -4361,10 +4617,10 @@ var BORROWED_BASE = 0.5;
|
|
|
4361
4617
|
var SECONDARY_DOMINANT_TARGETS = [2, 4, 5, 6];
|
|
4362
4618
|
function secondaryDominantTargets(key) {
|
|
4363
4619
|
const tonicizable = new Map(
|
|
4364
|
-
|
|
4620
|
+
_chunkYDGMWH43cjs.tonicizableDegrees.call(void 0, key).map((degree) => [degree.degreeNumber, degree])
|
|
4365
4621
|
);
|
|
4366
4622
|
return SECONDARY_DOMINANT_TARGETS.map((degree) => tonicizable.get(degree)).filter(
|
|
4367
|
-
(degree) => degree !== void 0
|
|
4623
|
+
(degree) => degree !== void 0 && !_chunkYDGMWH43cjs.isNativeDominantSeventh.call(void 0, degree.rootPc + 7, key)
|
|
4368
4624
|
);
|
|
4369
4625
|
}
|
|
4370
4626
|
var SECONDARY_DOMINANT_ENTRY_ORDER = [5, 6, 2, 4];
|
|
@@ -4379,23 +4635,24 @@ var REHARMONIZE_DIAL = {
|
|
|
4379
4635
|
function admittedCount(fraction, size) {
|
|
4380
4636
|
return Math.max(0, Math.min(size, Math.ceil(fraction * size)));
|
|
4381
4637
|
}
|
|
4382
|
-
function buildCandidates(
|
|
4383
|
-
const
|
|
4384
|
-
const
|
|
4385
|
-
const
|
|
4638
|
+
function buildCandidates(keyLike, harmonic) {
|
|
4639
|
+
const { scale: key, tonic } = _chunkYDGMWH43cjs.resolveKey.call(void 0, keyLike);
|
|
4640
|
+
const tonicPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
4641
|
+
const frame = _chunkYDGMWH43cjs.heptatonicFrameOf.call(void 0, key);
|
|
4642
|
+
const tones = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, frame);
|
|
4386
4643
|
const candidates = tones.map((rootPc, index) => {
|
|
4387
4644
|
const degree = index + 1;
|
|
4388
|
-
const quality =
|
|
4645
|
+
const quality = _chunkYDGMWH43cjs.diatonicTriad.call(void 0, degree, { ...frame, tonic }).quality;
|
|
4389
4646
|
return {
|
|
4390
4647
|
rootPc,
|
|
4391
4648
|
quality,
|
|
4392
4649
|
degree,
|
|
4393
4650
|
secondaryDominant: false,
|
|
4394
4651
|
base: vocabularyBase(rootPc, quality, tonicPc),
|
|
4395
|
-
pcs:
|
|
4652
|
+
pcs: _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, rootPc, quality))
|
|
4396
4653
|
};
|
|
4397
4654
|
});
|
|
4398
|
-
if (cadencesThroughRaisedSeventh(key)) {
|
|
4655
|
+
if (_chunkYDGMWH43cjs.cadencesThroughRaisedSeventh.call(void 0, key)) {
|
|
4399
4656
|
const rootPc = (tonicPc + 7) % 12;
|
|
4400
4657
|
candidates.push({
|
|
4401
4658
|
rootPc,
|
|
@@ -4403,7 +4660,7 @@ function buildCandidates(key, harmonic) {
|
|
|
4403
4660
|
degree: 5,
|
|
4404
4661
|
secondaryDominant: false,
|
|
4405
4662
|
base: vocabularyBase(rootPc, "maj", tonicPc),
|
|
4406
|
-
pcs:
|
|
4663
|
+
pcs: _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, rootPc, "maj"))
|
|
4407
4664
|
});
|
|
4408
4665
|
}
|
|
4409
4666
|
const targets = secondaryDominantTargets(key);
|
|
@@ -4422,20 +4679,20 @@ function buildCandidates(key, harmonic) {
|
|
|
4422
4679
|
secondaryDominant: true,
|
|
4423
4680
|
targetDegree: target.degreeNumber,
|
|
4424
4681
|
base: SECONDARY_DOMINANT_BASE,
|
|
4425
|
-
pcs:
|
|
4682
|
+
pcs: _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, rootPc, "dom7"))
|
|
4426
4683
|
});
|
|
4427
4684
|
}
|
|
4428
|
-
const parallel =
|
|
4429
|
-
const parallelTones =
|
|
4685
|
+
const parallel = _chunkLQZQDBCDcjs.parallelKey.call(void 0, key);
|
|
4686
|
+
const parallelTones = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, parallel);
|
|
4430
4687
|
const borrowed = [];
|
|
4431
4688
|
for (let degree = 1; degree <= parallelTones.length; degree += 1) {
|
|
4432
|
-
const chord =
|
|
4433
|
-
if (!
|
|
4689
|
+
const chord = _chunkYDGMWH43cjs.diatonicTriad.call(void 0, degree, { ...parallel, tonic });
|
|
4690
|
+
if (!_chunkLQZQDBCDcjs.isDiatonic.call(void 0, chord, key)) {
|
|
4434
4691
|
borrowed.push(chord);
|
|
4435
4692
|
}
|
|
4436
4693
|
}
|
|
4437
4694
|
const borrowedRank = (chord) => {
|
|
4438
|
-
const offset = BORROWED_ENTRY_ORDER.indexOf(
|
|
4695
|
+
const offset = BORROWED_ENTRY_ORDER.indexOf(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc - tonicPc));
|
|
4439
4696
|
return offset < 0 ? BORROWED_ENTRY_ORDER.length : offset;
|
|
4440
4697
|
};
|
|
4441
4698
|
borrowed.sort((a, b) => borrowedRank(a) - borrowedRank(b));
|
|
@@ -4454,7 +4711,7 @@ function buildCandidates(key, harmonic) {
|
|
|
4454
4711
|
// which of the two a phrase took was decided by the tie-break jitter
|
|
4455
4712
|
// rather than by the melody.
|
|
4456
4713
|
base: UNSTABLE_QUALITIES.has(chord.quality) ? Math.max(BORROWED_BASE, UNSTABLE_TRIAD) : BORROWED_BASE,
|
|
4457
|
-
pcs:
|
|
4714
|
+
pcs: _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord)
|
|
4458
4715
|
});
|
|
4459
4716
|
}
|
|
4460
4717
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4470,26 +4727,29 @@ function buildCandidates(key, harmonic) {
|
|
|
4470
4727
|
|
|
4471
4728
|
// src/generate/harmonize/index.ts
|
|
4472
4729
|
function harmonizeMelody(opts) {
|
|
4473
|
-
|
|
4474
|
-
|
|
4730
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "harmonize options");
|
|
4731
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, opts.melody, "harmonize melody", {
|
|
4475
4732
|
allowNonPositiveDuration: true,
|
|
4476
4733
|
budget: opts.budget
|
|
4477
4734
|
});
|
|
4478
|
-
const phraseEnds = _nullishCoalesce(opts.phraseEnds, () => ( []));
|
|
4735
|
+
const phraseEnds = _chunkS3QELJUEcjs.assertArray.call(void 0, _nullishCoalesce(opts.phraseEnds, () => ( [])), "harmonize phrase ends");
|
|
4479
4736
|
for (const end of phraseEnds) {
|
|
4480
|
-
|
|
4737
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, end, "harmonize phrase end");
|
|
4481
4738
|
}
|
|
4482
|
-
const soundingMelody =
|
|
4483
|
-
const ts =
|
|
4484
|
-
|
|
4739
|
+
const soundingMelody = inOnsetOrder(_chunkS3QELJUEcjs.soundingNotesOnly.call(void 0, opts.melody));
|
|
4740
|
+
const ts = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_METER)), "ts"));
|
|
4741
|
+
_chunkS3QELJUEcjs.assertTimeSignature.call(void 0, ts);
|
|
4485
4742
|
const requestedKey = _nullishCoalesce(opts.key, () => ( "infer"));
|
|
4486
|
-
const resolvedKey =
|
|
4743
|
+
const resolvedKey = _chunkYDGMWH43cjs.resolveKey.call(void 0,
|
|
4487
4744
|
requestedKey === "infer" ? inferKey(soundingMelody) : requestedKey
|
|
4488
4745
|
);
|
|
4489
4746
|
const key = resolvedKey.scale;
|
|
4490
|
-
const placement =
|
|
4747
|
+
const placement = _chunkS3QELJUEcjs.assertRecord.call(void 0,
|
|
4748
|
+
_nullishCoalesce(opts.placement, () => ( DEFAULT_PLACEMENT)),
|
|
4749
|
+
"harmonize placement"
|
|
4750
|
+
);
|
|
4491
4751
|
const ctx = resolveContext(opts.ctx);
|
|
4492
|
-
const reharmonize =
|
|
4752
|
+
const reharmonize = _chunkS3QELJUEcjs.assertOneOf.call(void 0,
|
|
4493
4753
|
_nullishCoalesce(opts.reharmonize, () => ( "diatonic")),
|
|
4494
4754
|
REHARMONIZE_STRENGTHS,
|
|
4495
4755
|
"reharmonize"
|
|
@@ -4498,11 +4758,11 @@ function harmonizeMelody(opts) {
|
|
|
4498
4758
|
if (soundingMelody.length === 0) {
|
|
4499
4759
|
return { transposeSemitones: 0, key: resolvedKey, chords: [], melodyRoles: [] };
|
|
4500
4760
|
}
|
|
4501
|
-
const candidates = buildCandidates(
|
|
4761
|
+
const candidates = buildCandidates(resolvedKey, harmonic);
|
|
4502
4762
|
const candAt = (i) => _nullishCoalesce(candidates[i], () => ( FALLBACK));
|
|
4503
4763
|
const draw = ctx.part("harmony");
|
|
4504
4764
|
const jitter = candidates.map((_, index) => draw.at("jitter", index) * TIE_BREAK_JITTER2);
|
|
4505
|
-
const pulse2 =
|
|
4765
|
+
const pulse2 = _chunkS3QELJUEcjs.pulseBeats.call(void 0, ts);
|
|
4506
4766
|
const spans = soundingMelody.map((note2) => ({
|
|
4507
4767
|
startBeat: snapToPulse(note2.startBeat, pulse2),
|
|
4508
4768
|
endBeat: snapToPulse(note2.startBeat + note2.durationBeat, pulse2)
|
|
@@ -4515,7 +4775,7 @@ function harmonizeMelody(opts) {
|
|
|
4515
4775
|
(end, span) => Math.max(end, span.endBeat),
|
|
4516
4776
|
Number.NEGATIVE_INFINITY
|
|
4517
4777
|
);
|
|
4518
|
-
const hr =
|
|
4778
|
+
const hr = _chunkS3QELJUEcjs.assertRange.call(void 0,
|
|
4519
4779
|
_nullishCoalesce(opts.harmonicRhythm, () => ( defaultHarmonicRhythm(ts))),
|
|
4520
4780
|
Number.MIN_VALUE,
|
|
4521
4781
|
Number.MAX_SAFE_INTEGER,
|
|
@@ -4544,11 +4804,12 @@ function harmonizeMelody(opts) {
|
|
|
4544
4804
|
}
|
|
4545
4805
|
const octaveShifts = placement.octaveSearch ? [0, -12, 12] : [0];
|
|
4546
4806
|
const transposes = semitoneShifts.flatMap((s) => octaveShifts.map((o) => s + o));
|
|
4547
|
-
|
|
4807
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0,
|
|
4548
4808
|
transposes.length * segments.length * candidates.length * candidates.length,
|
|
4549
4809
|
"harmonization placement search",
|
|
4550
4810
|
opts.budget
|
|
4551
4811
|
);
|
|
4812
|
+
let bestFit = Number.POSITIVE_INFINITY;
|
|
4552
4813
|
let bestCost = Number.POSITIVE_INFINITY;
|
|
4553
4814
|
let bestTs = 0;
|
|
4554
4815
|
let bestPath = [];
|
|
@@ -4563,8 +4824,10 @@ function harmonizeMelody(opts) {
|
|
|
4563
4824
|
closingSegments,
|
|
4564
4825
|
articulatedSegments
|
|
4565
4826
|
);
|
|
4566
|
-
const
|
|
4567
|
-
|
|
4827
|
+
const fit = keyFitCost(shifted, key);
|
|
4828
|
+
const total = cost + tessituraCost(shifted);
|
|
4829
|
+
if (fit < bestFit || fit === bestFit && total < bestCost) {
|
|
4830
|
+
bestFit = fit;
|
|
4568
4831
|
bestCost = total;
|
|
4569
4832
|
bestTs = shift;
|
|
4570
4833
|
bestPath = path;
|
|
@@ -4576,7 +4839,7 @@ function harmonizeMelody(opts) {
|
|
|
4576
4839
|
const chord = {
|
|
4577
4840
|
rootPc: cand.rootPc,
|
|
4578
4841
|
quality: cand.quality,
|
|
4579
|
-
startBeat: _nullishCoalesce(_optionalChain([segments, 'access',
|
|
4842
|
+
startBeat: _nullishCoalesce(_optionalChain([segments, 'access', _53 => _53[s], 'optionalAccess', _54 => _54.startBeat]), () => ( segmentStart + s * hr))
|
|
4580
4843
|
};
|
|
4581
4844
|
if (cand.degree !== void 0) {
|
|
4582
4845
|
chord.degree = cand.degree;
|
|
@@ -4590,8 +4853,8 @@ function harmonizeMelody(opts) {
|
|
|
4590
4853
|
const melodyRoles = opts.melody.map((note2, noteIndex) => {
|
|
4591
4854
|
const segIdx = segmentIndexAt(bounds, snapToPulse(note2.startBeat, pulse2));
|
|
4592
4855
|
const cand = candAt(_nullishCoalesce(bestPath[segIdx], () => ( 0)));
|
|
4593
|
-
const chord =
|
|
4594
|
-
return { noteIndex, role:
|
|
4856
|
+
const chord = _chunkYDGMWH43cjs.makeChord.call(void 0, cand.rootPc, cand.quality);
|
|
4857
|
+
return { noteIndex, role: _chunkP3CPXAJ5cjs.roleOf.call(void 0, note2.pitch + bestTs, chord).role };
|
|
4595
4858
|
});
|
|
4596
4859
|
return { transposeSemitones: bestTs, key: resolvedKey, chords, melodyRoles };
|
|
4597
4860
|
}
|
|
@@ -4610,15 +4873,15 @@ var MIN_TILE_SPAN = 1 / 256;
|
|
|
4610
4873
|
var DEFAULT_TS4 = { numerator: 4, denominator: 4 };
|
|
4611
4874
|
function isDownbeat(startBeat, barBeats) {
|
|
4612
4875
|
const bar2 = startBeat / barBeats;
|
|
4613
|
-
return Math.abs(bar2 - Math.round(bar2)) <
|
|
4876
|
+
return Math.abs(bar2 - Math.round(bar2)) < _chunkS3QELJUEcjs.BEAT_EPS;
|
|
4614
4877
|
}
|
|
4615
4878
|
function nearestChordTone(pitch, chord) {
|
|
4616
|
-
const pcs =
|
|
4879
|
+
const pcs = _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord);
|
|
4617
4880
|
for (let d = 0; d <= 12; d += 1) {
|
|
4618
|
-
if (pcs.includes(
|
|
4881
|
+
if (pcs.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch - d))) {
|
|
4619
4882
|
return pitch - d;
|
|
4620
4883
|
}
|
|
4621
|
-
if (pcs.includes(
|
|
4884
|
+
if (pcs.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch + d))) {
|
|
4622
4885
|
return pitch + d;
|
|
4623
4886
|
}
|
|
4624
4887
|
}
|
|
@@ -4675,7 +4938,7 @@ function pivotPitch(notes) {
|
|
|
4675
4938
|
pivot = note2;
|
|
4676
4939
|
}
|
|
4677
4940
|
}
|
|
4678
|
-
return _nullishCoalesce(_optionalChain([pivot, 'optionalAccess',
|
|
4941
|
+
return _nullishCoalesce(_optionalChain([pivot, 'optionalAccess', _55 => _55.pitch]), () => ( 0));
|
|
4679
4942
|
}
|
|
4680
4943
|
function contourOffsets(contour, count) {
|
|
4681
4944
|
const offsets = [];
|
|
@@ -4698,20 +4961,24 @@ function contourOffsets(contour, count) {
|
|
|
4698
4961
|
return offsets;
|
|
4699
4962
|
}
|
|
4700
4963
|
function generateMotif(opts) {
|
|
4701
|
-
|
|
4702
|
-
const contour =
|
|
4703
|
-
|
|
4704
|
-
|
|
4964
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "motif options");
|
|
4965
|
+
const contour = _chunkS3QELJUEcjs.assertOneOf.call(void 0,
|
|
4966
|
+
_nullishCoalesce(opts.contour, () => ( "arch")),
|
|
4967
|
+
["arch", "ascending", "descending", "wave"],
|
|
4968
|
+
"motif contour"
|
|
4969
|
+
);
|
|
4970
|
+
const bars = _chunkS3QELJUEcjs.assertPositiveInt.call(void 0, opts.bars, "motif bars");
|
|
4971
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_TS4)), "ts")));
|
|
4705
4972
|
const totalBeats = bars * barBeats;
|
|
4706
4973
|
const noteCount = Math.max(3, bars * 2);
|
|
4707
|
-
|
|
4974
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, noteCount, "motif notes");
|
|
4708
4975
|
const beatsPerNote = totalBeats / noteCount;
|
|
4709
4976
|
const ctx = resolveContextWith(opts.ctx, { ornament: opts.jitter });
|
|
4710
4977
|
const jitterProb = _nullishCoalesce(ctx.ornament, () => ( 0));
|
|
4711
4978
|
const draw = ctx.part("motif");
|
|
4712
|
-
const key =
|
|
4713
|
-
const chord = opts.chord ?
|
|
4714
|
-
const tonic =
|
|
4979
|
+
const key = _chunkYDGMWH43cjs.toKeyScale.call(void 0, opts.key);
|
|
4980
|
+
const chord = opts.chord ? _chunkYDGMWH43cjs.toChordData.call(void 0, opts.chord) : null;
|
|
4981
|
+
const tonic = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc) + 60;
|
|
4715
4982
|
const offsets = contourOffsets(contour, noteCount);
|
|
4716
4983
|
const notes = [];
|
|
4717
4984
|
for (let i = 0; i < noteCount; i += 1) {
|
|
@@ -4719,13 +4986,13 @@ function generateMotif(opts) {
|
|
|
4719
4986
|
if (draw.prob(jitterProb, "jitter", i)) {
|
|
4720
4987
|
jitter = draw.prob(0.5, "direction", i) ? 1 : -1;
|
|
4721
4988
|
}
|
|
4722
|
-
let pitch =
|
|
4989
|
+
let pitch = _chunkYDGMWH43cjs.shiftByScaleDegrees.call(void 0, tonic, (_nullishCoalesce(offsets[i], () => ( 0))) + jitter, key);
|
|
4723
4990
|
const startBeat = i * beatsPerNote;
|
|
4724
4991
|
if (chord && isDownbeat(startBeat, barBeats)) {
|
|
4725
4992
|
pitch = nearestChordTone(pitch, chord);
|
|
4726
4993
|
}
|
|
4727
4994
|
notes.push({
|
|
4728
|
-
pitch:
|
|
4995
|
+
pitch: _chunkS3QELJUEcjs.clampToMidi.call(void 0, pitch, "generated motif pitch"),
|
|
4729
4996
|
startBeat,
|
|
4730
4997
|
durationBeat: beatsPerNote
|
|
4731
4998
|
});
|
|
@@ -4736,12 +5003,12 @@ function motifToNoteEvents(cell) {
|
|
|
4736
5003
|
return assertCellNotes(cell, "motif cell notes").map((note2) => ({ ...note2 }));
|
|
4737
5004
|
}
|
|
4738
5005
|
function assertCellNotes(cell, name) {
|
|
4739
|
-
const read =
|
|
4740
|
-
|
|
5006
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, cell, "motif cell");
|
|
5007
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, read.notes, name);
|
|
4741
5008
|
return read.notes;
|
|
4742
5009
|
}
|
|
4743
5010
|
function transformMotif(cell, t, amount, key) {
|
|
4744
|
-
return transformCell(cell, t, amount, key === void 0 ? void 0 :
|
|
5011
|
+
return transformCell(cell, t, amount, key === void 0 ? void 0 : _chunkYDGMWH43cjs.toKeyScale.call(void 0, key));
|
|
4745
5012
|
}
|
|
4746
5013
|
function transformCell(cell, t, amount, key) {
|
|
4747
5014
|
return assertInRange(inTimeOrder(transformUnchecked(cell, t, amount, key)));
|
|
@@ -4749,7 +5016,7 @@ function transformCell(cell, t, amount, key) {
|
|
|
4749
5016
|
function assertInRange(cell) {
|
|
4750
5017
|
for (const note2 of cell.notes) {
|
|
4751
5018
|
if (note2.pitch < 0 || note2.pitch > 127) {
|
|
4752
|
-
throw new (0,
|
|
5019
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4753
5020
|
`transformed motif pitch ${note2.pitch} is outside the MIDI range 0..127`
|
|
4754
5021
|
);
|
|
4755
5022
|
}
|
|
@@ -4758,18 +5025,18 @@ function assertInRange(cell) {
|
|
|
4758
5025
|
}
|
|
4759
5026
|
function transformUnchecked(cell, t, amount, key) {
|
|
4760
5027
|
const notes = assertCellNotes(cell, "motif notes");
|
|
4761
|
-
|
|
5028
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, t, MOTIF_TRANSFORMS, "motif transform");
|
|
4762
5029
|
if (amount !== void 0) {
|
|
4763
|
-
|
|
5030
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, amount, "motif transform amount");
|
|
4764
5031
|
}
|
|
4765
5032
|
if ((t === "transposeChromatic" || t === "transposeDiatonic" || t === "sequence") && amount !== void 0) {
|
|
4766
|
-
|
|
5033
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0,
|
|
4767
5034
|
amount,
|
|
4768
5035
|
`${t === "transposeChromatic" ? "chromatic" : "diatonic"} transform amount`
|
|
4769
5036
|
);
|
|
4770
5037
|
}
|
|
4771
5038
|
if ((t === "augment" || t === "diminish") && amount !== void 0 && amount <= 0) {
|
|
4772
|
-
throw new (0,
|
|
5039
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("time transform amount must be positive");
|
|
4773
5040
|
}
|
|
4774
5041
|
switch (t) {
|
|
4775
5042
|
case "transposeChromatic": {
|
|
@@ -4787,7 +5054,7 @@ function transformUnchecked(cell, t, amount, key) {
|
|
|
4787
5054
|
// notes a motif is written with — a blues lick, a semitone neighbour —
|
|
4788
5055
|
// come through as themselves, and shifting by no degrees returns the
|
|
4789
5056
|
// cell it was given.
|
|
4790
|
-
pitch: key ?
|
|
5057
|
+
pitch: key ? _chunkYDGMWH43cjs.shiftByScaleDegrees.call(void 0, n.pitch, degrees, key) : n.pitch + degrees
|
|
4791
5058
|
}))
|
|
4792
5059
|
};
|
|
4793
5060
|
}
|
|
@@ -4833,40 +5100,48 @@ function scaleTime(cell, factor) {
|
|
|
4833
5100
|
};
|
|
4834
5101
|
}
|
|
4835
5102
|
function developMotif(cell, timeline, key, bars, ts) {
|
|
4836
|
-
const meter =
|
|
4837
|
-
|
|
4838
|
-
|
|
5103
|
+
const meter = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, ts, "ts"));
|
|
5104
|
+
_chunkLQZQDBCDcjs.assertChordTimeline.call(void 0, timeline);
|
|
5105
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, bars, "development bars");
|
|
4839
5106
|
const cellNotes = assertCellNotes(cell, "motif notes");
|
|
4840
|
-
const scale =
|
|
5107
|
+
const scale = _chunkYDGMWH43cjs.toKeyScale.call(void 0, key);
|
|
4841
5108
|
const span = cellSpan(cell);
|
|
4842
|
-
const barBeats =
|
|
5109
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, meter);
|
|
4843
5110
|
const totalBeats = bars * barBeats;
|
|
4844
5111
|
const origin = cellOrigin(cellNotes);
|
|
4845
5112
|
const out = [];
|
|
4846
5113
|
if (span <= 0) {
|
|
4847
5114
|
return inTimeOrder(cell);
|
|
4848
5115
|
}
|
|
5116
|
+
const line = _chunkKMYGRFZ6cjs.canonicalNoteOrder.call(void 0, cellNotes).flatMap((index) => {
|
|
5117
|
+
const note2 = cellNotes[index];
|
|
5118
|
+
return note2 === void 0 ? [] : [note2];
|
|
5119
|
+
});
|
|
4849
5120
|
const tileSpan = Math.max(span, MIN_TILE_SPAN);
|
|
4850
5121
|
const tileCount = Math.ceil(totalBeats / tileSpan);
|
|
4851
|
-
|
|
5122
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, tileCount * cellNotes.length, "developed motif notes");
|
|
4852
5123
|
for (let k = 0; k < tileCount; k += 1) {
|
|
4853
5124
|
const offset = k * tileSpan;
|
|
4854
5125
|
const taken = /* @__PURE__ */ new Map();
|
|
4855
5126
|
let previous;
|
|
4856
|
-
for (const n of
|
|
5127
|
+
for (const n of line) {
|
|
4857
5128
|
const startBeat = offset + (n.startBeat - origin);
|
|
4858
5129
|
if (startBeat >= totalBeats) {
|
|
4859
5130
|
continue;
|
|
4860
5131
|
}
|
|
4861
5132
|
const chord = timeline.at(startBeat);
|
|
4862
5133
|
const structural = n.startBeat === origin || isDownbeat(startBeat, barBeats);
|
|
4863
|
-
const chordTones = chord && structural ?
|
|
4864
|
-
const allows = chordTones ? (candidate) => chordTones.includes(
|
|
5134
|
+
const chordTones = chord && structural ? _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord) : null;
|
|
5135
|
+
const allows = chordTones ? (candidate) => chordTones.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, candidate)) : (candidate) => _chunkYDGMWH43cjs.isScaleTone.call(void 0, candidate, scale);
|
|
4865
5136
|
const direction = previous === void 0 ? 0 : n.pitch - previous;
|
|
4866
5137
|
const pitch = developedPitch(n.pitch, allows, direction, taken);
|
|
4867
5138
|
taken.set(pitch, n.pitch);
|
|
4868
5139
|
previous = n.pitch;
|
|
4869
|
-
out.push({
|
|
5140
|
+
out.push({
|
|
5141
|
+
pitch,
|
|
5142
|
+
startBeat,
|
|
5143
|
+
durationBeat: Math.min(n.durationBeat, totalBeats - startBeat)
|
|
5144
|
+
});
|
|
4870
5145
|
}
|
|
4871
5146
|
}
|
|
4872
5147
|
return inTimeOrder({ notes: out });
|
|
@@ -4875,9 +5150,16 @@ function developMotif(cell, timeline, key, bars, ts) {
|
|
|
4875
5150
|
// src/generate/plan/internal.ts
|
|
4876
5151
|
var STRONG_WEIGHT = 2;
|
|
4877
5152
|
function positionClass(beat, meters) {
|
|
4878
|
-
const weight =
|
|
5153
|
+
const weight = _chunkS3QELJUEcjs.metricWeight.call(void 0, beat, meters);
|
|
4879
5154
|
return weight >= STRONG_WEIGHT ? "strong" : weight > 0 ? "weak" : "off";
|
|
4880
5155
|
}
|
|
5156
|
+
function finalDownbeat(phrase, meters) {
|
|
5157
|
+
let downbeat = _chunkS3QELJUEcjs.barStartBeat.call(void 0, phrase.startBeat, meters);
|
|
5158
|
+
while (downbeat + _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, downbeat, meters) < phrase.endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5159
|
+
downbeat += _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, downbeat, meters);
|
|
5160
|
+
}
|
|
5161
|
+
return Math.max(downbeat, phrase.startBeat);
|
|
5162
|
+
}
|
|
4881
5163
|
|
|
4882
5164
|
// src/generate/plan/types.ts
|
|
4883
5165
|
var COMPOSITION_PLAN_VERSION = 1;
|
|
@@ -4906,85 +5188,85 @@ function plannedContourAt(shape, peakPosition, t) {
|
|
|
4906
5188
|
var MASS_TOLERANCE = 1e-9;
|
|
4907
5189
|
function assertString(value, name) {
|
|
4908
5190
|
if (typeof value !== "string") {
|
|
4909
|
-
throw new (0,
|
|
5191
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must be a string; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, value)}`);
|
|
4910
5192
|
}
|
|
4911
5193
|
return value;
|
|
4912
5194
|
}
|
|
4913
5195
|
function assertSpanOrder(startBeat, endBeat, name) {
|
|
4914
5196
|
if (endBeat < startBeat) {
|
|
4915
|
-
throw new (0,
|
|
5197
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
4916
5198
|
`${name}.endBeat must be at least ${name}.startBeat; received ${endBeat} < ${startBeat}`
|
|
4917
5199
|
);
|
|
4918
5200
|
}
|
|
4919
5201
|
}
|
|
4920
5202
|
function assertNullable(value, name, validate) {
|
|
4921
5203
|
if (value === void 0) {
|
|
4922
|
-
throw new (0,
|
|
5204
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must be present; received undefined`);
|
|
4923
5205
|
}
|
|
4924
5206
|
return value === null ? null : validate(value, name);
|
|
4925
5207
|
}
|
|
4926
5208
|
function assertMassDistribution(value, length, name) {
|
|
4927
|
-
const shares =
|
|
5209
|
+
const shares = _chunkS3QELJUEcjs.assertArray.call(void 0, value, name);
|
|
4928
5210
|
if (shares.length !== length) {
|
|
4929
|
-
throw new (0,
|
|
5211
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must have length ${length}; received ${shares.length}`);
|
|
4930
5212
|
}
|
|
4931
5213
|
let sum = 0;
|
|
4932
5214
|
for (let index = 0; index < shares.length; index += 1) {
|
|
4933
|
-
const share =
|
|
5215
|
+
const share = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, shares[index], `${name}[${index}]`);
|
|
4934
5216
|
if (share < 0) {
|
|
4935
|
-
throw new (0,
|
|
5217
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}[${index}] must be at least 0; received ${share}`);
|
|
4936
5218
|
}
|
|
4937
5219
|
sum += share;
|
|
4938
5220
|
}
|
|
4939
5221
|
if (Math.abs(sum - 1) > MASS_TOLERANCE) {
|
|
4940
|
-
throw new (0,
|
|
5222
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must sum to 1; received ${sum}`);
|
|
4941
5223
|
}
|
|
4942
5224
|
return shares;
|
|
4943
5225
|
}
|
|
4944
5226
|
function assertResolvedKeyField(value, name) {
|
|
4945
|
-
const read =
|
|
5227
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4946
5228
|
try {
|
|
4947
|
-
|
|
5229
|
+
_chunkYDGMWH43cjs.resolveKey.call(void 0, read);
|
|
4948
5230
|
} catch (error) {
|
|
4949
|
-
if (error instanceof
|
|
4950
|
-
throw new (0,
|
|
5231
|
+
if (error instanceof _chunkS3QELJUEcjs.InvalidInputError) {
|
|
5232
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name} must be a valid key: ${error.message}`);
|
|
4951
5233
|
}
|
|
4952
5234
|
throw error;
|
|
4953
5235
|
}
|
|
4954
5236
|
return read;
|
|
4955
5237
|
}
|
|
4956
5238
|
function assertPlannedSection(value, name) {
|
|
4957
|
-
const read =
|
|
5239
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
4958
5240
|
assertString(read.label, `${name}.label`);
|
|
4959
|
-
const startBeat =
|
|
4960
|
-
const endBeat =
|
|
5241
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
5242
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
4961
5243
|
assertSpanOrder(startBeat, endBeat, name);
|
|
4962
5244
|
return read;
|
|
4963
5245
|
}
|
|
4964
5246
|
function assertPlannedPhrase(value, name, sectionCount, motifCount) {
|
|
4965
|
-
const read =
|
|
4966
|
-
const startBeat =
|
|
4967
|
-
const endBeat =
|
|
5247
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
5248
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
5249
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
4968
5250
|
assertSpanOrder(startBeat, endBeat, name);
|
|
4969
5251
|
assertNullable(
|
|
4970
5252
|
read.section,
|
|
4971
5253
|
`${name}.section`,
|
|
4972
|
-
(v, n) =>
|
|
5254
|
+
(v, n) => _chunkS3QELJUEcjs.assertInteger.call(void 0, v, n, 0, Math.max(sectionCount - 1, 0))
|
|
4973
5255
|
);
|
|
4974
|
-
assertNullable(read.cadence, `${name}.cadence`, (v, n) =>
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
const register =
|
|
5256
|
+
assertNullable(read.cadence, `${name}.cadence`, (v, n) => _chunkS3QELJUEcjs.assertOneOf.call(void 0, v, _chunkLQZQDBCDcjs.CADENCE_TYPES, n));
|
|
5257
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, read.shape, _chunkLQZQDBCDcjs.MELODIC_CONTOUR_SHAPES, `${name}.shape`);
|
|
5258
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.peakPosition, 0, 1, `${name}.peakPosition`);
|
|
5259
|
+
const register = _chunkS3QELJUEcjs.assertRecord.call(void 0,
|
|
4978
5260
|
read.register,
|
|
4979
5261
|
`${name}.register`
|
|
4980
5262
|
);
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
const motifs =
|
|
5263
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, register.low, `${name}.register.low`);
|
|
5264
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, register.high, `${name}.register.high`);
|
|
5265
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, register.mean, 0, 127, `${name}.register.mean`);
|
|
5266
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.onsetDensity, 0, Number.MAX_SAFE_INTEGER, `${name}.onsetDensity`);
|
|
5267
|
+
const motifs = _chunkS3QELJUEcjs.assertArray.call(void 0, read.motifs, `${name}.motifs`);
|
|
4986
5268
|
for (let index = 0; index < motifs.length; index += 1) {
|
|
4987
|
-
|
|
5269
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0,
|
|
4988
5270
|
motifs[index],
|
|
4989
5271
|
`${name}.motifs[${index}]`,
|
|
4990
5272
|
0,
|
|
@@ -4994,18 +5276,18 @@ function assertPlannedPhrase(value, name, sectionCount, motifCount) {
|
|
|
4994
5276
|
return read;
|
|
4995
5277
|
}
|
|
4996
5278
|
function assertPlannedChord(value, name, keys) {
|
|
4997
|
-
const read =
|
|
4998
|
-
const startBeat =
|
|
4999
|
-
const endBeat =
|
|
5279
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
5280
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
5281
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
5000
5282
|
assertSpanOrder(startBeat, endBeat, name);
|
|
5001
|
-
const keyIndex =
|
|
5283
|
+
const keyIndex = _chunkS3QELJUEcjs.assertInteger.call(void 0, read.key, `${name}.key`, 0, Math.max(keys.length - 1, 0));
|
|
5002
5284
|
const roman = assertString(read.roman, `${name}.roman`);
|
|
5003
5285
|
try {
|
|
5004
|
-
|
|
5286
|
+
_chunkLQZQDBCDcjs.romanToChord.call(void 0, roman, keys[keyIndex]);
|
|
5005
5287
|
} catch (error) {
|
|
5006
|
-
if (error instanceof
|
|
5007
|
-
throw new (0,
|
|
5008
|
-
`${name}.roman must be readable by romanToChord; received ${
|
|
5288
|
+
if (error instanceof _chunkS3QELJUEcjs.InvalidInputError) {
|
|
5289
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
5290
|
+
`${name}.roman must be readable by romanToChord; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, roman)}: ${error.message}`
|
|
5009
5291
|
);
|
|
5010
5292
|
}
|
|
5011
5293
|
throw error;
|
|
@@ -5013,64 +5295,64 @@ function assertPlannedChord(value, name, keys) {
|
|
|
5013
5295
|
return read;
|
|
5014
5296
|
}
|
|
5015
5297
|
function assertPlannedMotifRelation(value, name) {
|
|
5016
|
-
const read =
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5298
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
5299
|
+
_chunkS3QELJUEcjs.assertOneOf.call(void 0, read.kind, _chunkLQZQDBCDcjs.MOTIF_RELATION_KINDS, `${name}.kind`);
|
|
5300
|
+
_chunkS3QELJUEcjs.assertFlag.call(void 0, read.sequence, `${name}.sequence`);
|
|
5301
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.semitones, `${name}.semitones`);
|
|
5020
5302
|
if (read.kind === "tonalTransposition") {
|
|
5021
|
-
|
|
5303
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.degrees, `${name}.degrees`);
|
|
5022
5304
|
} else if (read.degrees !== void 0) {
|
|
5023
|
-
|
|
5305
|
+
_chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.degrees, `${name}.degrees`);
|
|
5024
5306
|
}
|
|
5025
|
-
const timeRatio =
|
|
5307
|
+
const timeRatio = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.timeRatio, `${name}.timeRatio`);
|
|
5026
5308
|
if (timeRatio <= 0) {
|
|
5027
|
-
throw new (0,
|
|
5309
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}.timeRatio must be positive; received ${timeRatio}`);
|
|
5028
5310
|
}
|
|
5029
5311
|
return read;
|
|
5030
5312
|
}
|
|
5031
5313
|
function assertPlannedMotif(value, name, ownIndex, motifCount, phraseCount) {
|
|
5032
|
-
const read =
|
|
5033
|
-
|
|
5034
|
-
const startBeat =
|
|
5035
|
-
const endBeat =
|
|
5314
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
5315
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, read.phrase, `${name}.phrase`, 0, Math.max(phraseCount - 1, 0));
|
|
5316
|
+
const startBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
|
|
5317
|
+
const endBeat = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.endBeat`);
|
|
5036
5318
|
assertSpanOrder(startBeat, endBeat, name);
|
|
5037
|
-
|
|
5319
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, read.notes, `${name}.notes`);
|
|
5038
5320
|
const from = assertNullable(
|
|
5039
5321
|
read.from,
|
|
5040
5322
|
`${name}.from`,
|
|
5041
|
-
(v, n) =>
|
|
5323
|
+
(v, n) => _chunkS3QELJUEcjs.assertInteger.call(void 0, v, n, 0, Math.max(motifCount - 1, 0))
|
|
5042
5324
|
);
|
|
5043
5325
|
if (from !== null && from >= ownIndex) {
|
|
5044
|
-
throw new (0,
|
|
5326
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
5045
5327
|
`${name}.from must be less than this motif's own index (${ownIndex}); received ${from}`
|
|
5046
5328
|
);
|
|
5047
5329
|
}
|
|
5048
5330
|
const relation = assertNullable(read.relation, `${name}.relation`, assertPlannedMotifRelation);
|
|
5049
5331
|
if (from === null && relation !== null) {
|
|
5050
|
-
throw new (0,
|
|
5332
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
5051
5333
|
`${name}.relation must be null for a root motif (from = null); received a relation`
|
|
5052
5334
|
);
|
|
5053
5335
|
}
|
|
5054
|
-
const rhythm = assertNullable(read.rhythm, `${name}.rhythm`, (v, n) =>
|
|
5336
|
+
const rhythm = assertNullable(read.rhythm, `${name}.rhythm`, (v, n) => _chunkS3QELJUEcjs.assertArray.call(void 0, v, n));
|
|
5055
5337
|
if (rhythm !== null) {
|
|
5056
5338
|
if (from !== null) {
|
|
5057
|
-
throw new (0,
|
|
5339
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}.rhythm must be null for a derived statement`);
|
|
5058
5340
|
}
|
|
5059
5341
|
if (rhythm.length !== read.notes - 1) {
|
|
5060
|
-
throw new (0,
|
|
5342
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
5061
5343
|
`${name}.rhythm must hold notes - 1 (${read.notes - 1}) gaps; received ${rhythm.length}`
|
|
5062
5344
|
);
|
|
5063
5345
|
}
|
|
5064
5346
|
let total = 0;
|
|
5065
5347
|
for (let index = 0; index < rhythm.length; index += 1) {
|
|
5066
|
-
const gap =
|
|
5348
|
+
const gap = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, rhythm[index], `${name}.rhythm[${index}]`);
|
|
5067
5349
|
if (gap <= 0) {
|
|
5068
|
-
throw new (0,
|
|
5350
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}.rhythm[${index}] must be positive; received ${gap}`);
|
|
5069
5351
|
}
|
|
5070
5352
|
total += gap;
|
|
5071
5353
|
}
|
|
5072
|
-
if (total >= endBeat - startBeat -
|
|
5073
|
-
throw new (0,
|
|
5354
|
+
if (total >= endBeat - startBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5355
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
5074
5356
|
`${name}.rhythm must sum to less than the statement's length (${endBeat - startBeat}); received ${total}`
|
|
5075
5357
|
);
|
|
5076
5358
|
}
|
|
@@ -5078,48 +5360,48 @@ function assertPlannedMotif(value, name, ownIndex, motifCount, phraseCount) {
|
|
|
5078
5360
|
return read;
|
|
5079
5361
|
}
|
|
5080
5362
|
function assertPlannedRhythm(value, name) {
|
|
5081
|
-
const read =
|
|
5363
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
5082
5364
|
assertMassDistribution(read.onsetLevels, 6, `${name}.onsetLevels`);
|
|
5083
|
-
assertMassDistribution(read.interOnsetShares,
|
|
5084
|
-
|
|
5365
|
+
assertMassDistribution(read.interOnsetShares, _chunkLQZQDBCDcjs.RHYTHM_IOI_BINS.length, `${name}.interOnsetShares`);
|
|
5366
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, read.syncopation, 0, 1, `${name}.syncopation`);
|
|
5085
5367
|
return read;
|
|
5086
5368
|
}
|
|
5087
5369
|
function assertCompositionPlan(value, name = "composition plan") {
|
|
5088
|
-
const read =
|
|
5370
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
|
|
5089
5371
|
if (read.planVersion !== COMPOSITION_PLAN_VERSION) {
|
|
5090
|
-
throw new (0,
|
|
5091
|
-
`${name}.planVersion must be ${COMPOSITION_PLAN_VERSION}; received ${
|
|
5372
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
5373
|
+
`${name}.planVersion must be ${COMPOSITION_PLAN_VERSION}; received ${_chunkS3QELJUEcjs.describeRejected.call(void 0, read.planVersion)}`
|
|
5092
5374
|
);
|
|
5093
5375
|
}
|
|
5094
|
-
|
|
5095
|
-
|
|
5376
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, read.seed, `${name}.seed`, 0, 4294967295);
|
|
5377
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0,
|
|
5096
5378
|
read.algorithmVersion,
|
|
5097
5379
|
`${name}.algorithmVersion`,
|
|
5098
|
-
|
|
5099
|
-
|
|
5380
|
+
_chunkWOMCXN2Wcjs.MIN_ALGORITHM_VERSION,
|
|
5381
|
+
_chunkWOMCXN2Wcjs.ALGORITHM_VERSION
|
|
5100
5382
|
);
|
|
5101
|
-
const keys =
|
|
5383
|
+
const keys = _chunkS3QELJUEcjs.assertArray.call(void 0, read.keys, `${name}.keys`);
|
|
5102
5384
|
if (keys.length === 0) {
|
|
5103
|
-
throw new (0,
|
|
5385
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`${name}.keys must hold at least one key; received an empty array`);
|
|
5104
5386
|
}
|
|
5105
5387
|
for (let index = 0; index < keys.length; index += 1) {
|
|
5106
5388
|
assertResolvedKeyField(keys[index], `${name}.keys[${index}]`);
|
|
5107
5389
|
}
|
|
5108
|
-
|
|
5109
|
-
const span =
|
|
5390
|
+
_chunkS3QELJUEcjs.assertMeterMap.call(void 0, read.meters, `${name}.meters`);
|
|
5391
|
+
const span = _chunkS3QELJUEcjs.assertRecord.call(void 0,
|
|
5110
5392
|
read.span,
|
|
5111
5393
|
`${name}.span`
|
|
5112
5394
|
);
|
|
5113
|
-
const spanStart =
|
|
5114
|
-
const spanEnd =
|
|
5395
|
+
const spanStart = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, span.startBeat, `${name}.span.startBeat`);
|
|
5396
|
+
const spanEnd = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, span.endBeat, `${name}.span.endBeat`);
|
|
5115
5397
|
assertSpanOrder(spanStart, spanEnd, `${name}.span`);
|
|
5116
|
-
|
|
5117
|
-
const sections =
|
|
5398
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, span.bars, 0, Number.MAX_SAFE_INTEGER, `${name}.span.bars`);
|
|
5399
|
+
const sections = _chunkS3QELJUEcjs.assertArray.call(void 0, read.sections, `${name}.sections`);
|
|
5118
5400
|
for (let index = 0; index < sections.length; index += 1) {
|
|
5119
5401
|
assertPlannedSection(sections[index], `${name}.sections[${index}]`);
|
|
5120
5402
|
}
|
|
5121
|
-
const phrases =
|
|
5122
|
-
const motifs =
|
|
5403
|
+
const phrases = _chunkS3QELJUEcjs.assertArray.call(void 0, read.phrases, `${name}.phrases`);
|
|
5404
|
+
const motifs = _chunkS3QELJUEcjs.assertArray.call(void 0, read.motifs, `${name}.motifs`);
|
|
5123
5405
|
for (let index = 0; index < phrases.length; index += 1) {
|
|
5124
5406
|
assertPlannedPhrase(
|
|
5125
5407
|
phrases[index],
|
|
@@ -5128,7 +5410,7 @@ function assertCompositionPlan(value, name = "composition plan") {
|
|
|
5128
5410
|
motifs.length
|
|
5129
5411
|
);
|
|
5130
5412
|
}
|
|
5131
|
-
const harmony =
|
|
5413
|
+
const harmony = _chunkS3QELJUEcjs.assertArray.call(void 0, read.harmony, `${name}.harmony`);
|
|
5132
5414
|
for (let index = 0; index < harmony.length; index += 1) {
|
|
5133
5415
|
assertPlannedChord(harmony[index], `${name}.harmony[${index}]`, keys);
|
|
5134
5416
|
}
|
|
@@ -5152,13 +5434,13 @@ function planTimeline(plan) {
|
|
|
5152
5434
|
function planChordTimeline(plan) {
|
|
5153
5435
|
const spans = plan.harmony.map((chord) => {
|
|
5154
5436
|
const key = plan.keys[chord.key];
|
|
5155
|
-
return
|
|
5437
|
+
return _chunkYDGMWH43cjs.spanFromChord.call(void 0, _chunkLQZQDBCDcjs.romanToChord.call(void 0, chord.roman, key), chord.startBeat);
|
|
5156
5438
|
});
|
|
5157
|
-
return
|
|
5439
|
+
return _chunkLQZQDBCDcjs.chordTimelineFromChords.call(void 0, spans, plan.span.endBeat);
|
|
5158
5440
|
}
|
|
5159
5441
|
|
|
5160
5442
|
// src/generate/plan/harmony.ts
|
|
5161
|
-
var
|
|
5443
|
+
var HARMONY_OK_KIND_NAMES = [
|
|
5162
5444
|
"chordTone",
|
|
5163
5445
|
"tension",
|
|
5164
5446
|
"suspension",
|
|
@@ -5166,7 +5448,8 @@ var HARMONY_OK_KINDS = /* @__PURE__ */ new Set([
|
|
|
5166
5448
|
"anticipation",
|
|
5167
5449
|
"passing",
|
|
5168
5450
|
"neighbor"
|
|
5169
|
-
]
|
|
5451
|
+
];
|
|
5452
|
+
var HARMONY_OK_KINDS = new Set(HARMONY_OK_KIND_NAMES);
|
|
5170
5453
|
var CADENCE_DEGREES = {
|
|
5171
5454
|
authentic: [1, 3],
|
|
5172
5455
|
plagal: [1, 3],
|
|
@@ -5181,32 +5464,38 @@ function planKeyAt(plan) {
|
|
|
5181
5464
|
key: plan.keys[chord.key],
|
|
5182
5465
|
confidence: 1
|
|
5183
5466
|
}));
|
|
5184
|
-
return
|
|
5467
|
+
return _chunkLQZQDBCDcjs.keyLookup.call(void 0, regions, plan.keys[0]);
|
|
5185
5468
|
}
|
|
5186
5469
|
function cadencePitchClasses(plan, timeline, cadence, beat) {
|
|
5187
5470
|
if (cadence === "deceptive") {
|
|
5188
5471
|
const chord = timeline.at(beat);
|
|
5189
|
-
return chord === null ? null :
|
|
5472
|
+
return chord === null ? null : _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord);
|
|
5190
5473
|
}
|
|
5191
5474
|
const entry = plan.harmony.find((chord) => beat >= chord.startBeat && beat < chord.endBeat);
|
|
5192
|
-
const
|
|
5193
|
-
|
|
5475
|
+
const scale = _chunkYDGMWH43cjs.scaleOf.call(void 0, plan.keys[_nullishCoalesce(_optionalChain([entry, 'optionalAccess', _56 => _56.key]), () => ( 0))]);
|
|
5476
|
+
const tones = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, scale);
|
|
5477
|
+
const raised = _chunkYDGMWH43cjs.cadencesThroughRaisedSeventh.call(void 0, scale);
|
|
5478
|
+
return CADENCE_DEGREES[cadence].map((degree) => {
|
|
5479
|
+
const tone = tones[degree - 1];
|
|
5480
|
+
return raised && degree === 7 && tone !== void 0 ? _chunkYDGMWH43cjs.leadingTonePcOf.call(void 0, scale) : tone;
|
|
5481
|
+
}).filter((pc) => pc !== void 0);
|
|
5194
5482
|
}
|
|
5195
5483
|
function planHarmonyMisfits(plan, timeline = planChordTimeline(plan)) {
|
|
5196
5484
|
const keyAt = planKeyAt(plan);
|
|
5197
|
-
const scaleAt2 = (beat) =>
|
|
5485
|
+
const scaleAt2 = (beat) => _chunkYDGMWH43cjs.scaleOf.call(void 0, keyAt(beat));
|
|
5198
5486
|
return (line) => {
|
|
5199
|
-
const analyzed =
|
|
5487
|
+
const analyzed = _chunkLQZQDBCDcjs.analyzeVoice.call(void 0, line, timeline.at, scaleAt2);
|
|
5200
5488
|
return line.map((note2, index) => {
|
|
5201
5489
|
const position = positionClass(note2.startBeat, plan.meters);
|
|
5202
5490
|
if (position === "off") {
|
|
5203
5491
|
return null;
|
|
5204
5492
|
}
|
|
5205
|
-
const kinds = (_nullishCoalesce(_optionalChain([analyzed, 'access',
|
|
5493
|
+
const kinds = (_nullishCoalesce(_optionalChain([analyzed, 'access', _57 => _57[index], 'optionalAccess', _58 => _58.labels]), () => ( []))).map((label) => label.kind);
|
|
5206
5494
|
if (kinds.some((kind) => HARMONY_OK_KINDS.has(kind))) {
|
|
5207
5495
|
return null;
|
|
5208
5496
|
}
|
|
5209
|
-
|
|
5497
|
+
const lenient = position === "weak" || timeline.at(note2.startBeat) === null;
|
|
5498
|
+
return lenient && _chunkYDGMWH43cjs.isScaleTone.call(void 0, note2.pitch, scaleAt2(note2.startBeat)) ? null : kinds;
|
|
5210
5499
|
});
|
|
5211
5500
|
};
|
|
5212
5501
|
}
|
|
@@ -5243,7 +5532,7 @@ function leapOf(delta) {
|
|
|
5243
5532
|
function stepCost(from, to, leap, bothFixed) {
|
|
5244
5533
|
const delta = to - from;
|
|
5245
5534
|
const size = Math.abs(delta);
|
|
5246
|
-
if (!bothFixed &&
|
|
5535
|
+
if (!bothFixed && _chunkYDGMWH43cjs.isForbiddenMelodicLeap.call(void 0, from, to)) {
|
|
5247
5536
|
return Number.POSITIVE_INFINITY;
|
|
5248
5537
|
}
|
|
5249
5538
|
let cost = intervalCost(size);
|
|
@@ -5257,7 +5546,7 @@ function searchPitches(slots, budget, extra) {
|
|
|
5257
5546
|
if (first === void 0) {
|
|
5258
5547
|
return [];
|
|
5259
5548
|
}
|
|
5260
|
-
let previous =
|
|
5549
|
+
let previous = _chunkS3QELJUEcjs.allocateCandidateTable.call(void 0,
|
|
5261
5550
|
first.candidates.length,
|
|
5262
5551
|
LEAP_STATES,
|
|
5263
5552
|
SEARCH_LABEL,
|
|
@@ -5271,13 +5560,13 @@ function searchPitches(slots, budget, extra) {
|
|
|
5271
5560
|
const before = slots[k - 1];
|
|
5272
5561
|
const slot = slots[k];
|
|
5273
5562
|
const unary = slot.candidates.map((pitch) => slot.cost(pitch));
|
|
5274
|
-
const current =
|
|
5563
|
+
const current = _chunkS3QELJUEcjs.allocateCandidateTable.call(void 0,
|
|
5275
5564
|
slot.candidates.length,
|
|
5276
5565
|
LEAP_STATES,
|
|
5277
5566
|
SEARCH_LABEL,
|
|
5278
5567
|
budget
|
|
5279
5568
|
).fill(Number.POSITIVE_INFINITY);
|
|
5280
|
-
const back =
|
|
5569
|
+
const back = _chunkS3QELJUEcjs.allocateChoiceTable.call(void 0,
|
|
5281
5570
|
slot.candidates.length,
|
|
5282
5571
|
LEAP_STATES,
|
|
5283
5572
|
SEARCH_LABEL,
|
|
@@ -5341,16 +5630,19 @@ function stretched(cell, timeRatio) {
|
|
|
5341
5630
|
function shaped(cell, relation) {
|
|
5342
5631
|
switch (relation.kind) {
|
|
5343
5632
|
case "repetition":
|
|
5344
|
-
case "tonalTransposition":
|
|
5345
5633
|
return cell;
|
|
5346
5634
|
case "transposition":
|
|
5635
|
+
case "tonalTransposition":
|
|
5347
5636
|
return stretched(cell, relation.timeRatio);
|
|
5348
5637
|
case "inversion":
|
|
5349
5638
|
return stretched(transformMotif(cell, "invert"), relation.timeRatio);
|
|
5350
5639
|
case "retrograde":
|
|
5351
|
-
return transformMotif(cell, "retrograde");
|
|
5640
|
+
return stretched(transformMotif(cell, "retrograde"), relation.timeRatio);
|
|
5352
5641
|
case "retrogradeInversion":
|
|
5353
|
-
return
|
|
5642
|
+
return stretched(
|
|
5643
|
+
transformMotif(transformMotif(cell, "invert"), "retrograde"),
|
|
5644
|
+
relation.timeRatio
|
|
5645
|
+
);
|
|
5354
5646
|
case "augmentation":
|
|
5355
5647
|
return transformMotif(cell, "augment", relation.timeRatio);
|
|
5356
5648
|
case "diminution":
|
|
@@ -5388,12 +5680,12 @@ function replayAt(source, relation, level, startBeat, key) {
|
|
|
5388
5680
|
const shift = head.pitch + level - first.pitch;
|
|
5389
5681
|
return cell.notes.map((n) => ({
|
|
5390
5682
|
...n,
|
|
5391
|
-
pitch: relation.kind === "tonalTransposition" ?
|
|
5683
|
+
pitch: relation.kind === "tonalTransposition" ? _chunkYDGMWH43cjs.shiftByScaleDegrees.call(void 0, n.pitch, level, key) : n.pitch + shift,
|
|
5392
5684
|
startBeat: n.startBeat + offset
|
|
5393
5685
|
}));
|
|
5394
5686
|
}
|
|
5395
5687
|
function clipStatement(notes, endBeat) {
|
|
5396
|
-
return notes.filter((n) => n.startBeat < endBeat -
|
|
5688
|
+
return notes.filter((n) => n.startBeat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS).map((n) => ({ ...n, durationBeat: Math.min(n.durationBeat, endBeat - n.startBeat) }));
|
|
5397
5689
|
}
|
|
5398
5690
|
function outsideCount(notes, frame) {
|
|
5399
5691
|
return notes.filter((n) => n.pitch < frame.low || n.pitch > frame.high).length;
|
|
@@ -5413,7 +5705,7 @@ function repairStatement(notes, forced, frame) {
|
|
|
5413
5705
|
);
|
|
5414
5706
|
const pitches = searchPitches(slots, frame.budget);
|
|
5415
5707
|
if (pitches === null) {
|
|
5416
|
-
throw new (0,
|
|
5708
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(
|
|
5417
5709
|
`no repair fits the statement into the register ${frame.low}..${frame.high}`,
|
|
5418
5710
|
{ at: frame.at }
|
|
5419
5711
|
);
|
|
@@ -5481,7 +5773,7 @@ function varyStatement(source, startBeat, frame) {
|
|
|
5481
5773
|
)
|
|
5482
5774
|
);
|
|
5483
5775
|
if (pitches === null) {
|
|
5484
|
-
throw new (0,
|
|
5776
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(`no variation line fits the register ${frame.low}..${frame.high}`, {
|
|
5485
5777
|
at: frame.at
|
|
5486
5778
|
});
|
|
5487
5779
|
}
|
|
@@ -5502,9 +5794,9 @@ function melodyContext(plan, input) {
|
|
|
5502
5794
|
if (typeof input === "number") {
|
|
5503
5795
|
return resolveContext({ ...fromPlan, seed: input });
|
|
5504
5796
|
}
|
|
5505
|
-
const read =
|
|
5797
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, input, "ctx");
|
|
5506
5798
|
if (read.rng !== void 0) {
|
|
5507
|
-
throw new (0,
|
|
5799
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
5508
5800
|
"ctx.rng cannot drive a melody: every onset and tie-break is drawn at an address of phrase and beat under a seed; pass a seed instead"
|
|
5509
5801
|
);
|
|
5510
5802
|
}
|
|
@@ -5518,7 +5810,7 @@ function chordEntryAt(plan, beat) {
|
|
|
5518
5810
|
return plan.harmony.find((chord) => beat >= chord.startBeat && beat < chord.endBeat);
|
|
5519
5811
|
}
|
|
5520
5812
|
function scaleAt(scene, beat) {
|
|
5521
|
-
return scene.scales[_nullishCoalesce(_optionalChain([chordEntryAt, 'call',
|
|
5813
|
+
return scene.scales[_nullishCoalesce(_optionalChain([chordEntryAt, 'call', _59 => _59(scene.plan, beat), 'optionalAccess', _60 => _60.key]), () => ( 0))];
|
|
5522
5814
|
}
|
|
5523
5815
|
function targetPitch(phrase, beat) {
|
|
5524
5816
|
const length = phrase.endBeat - phrase.startBeat;
|
|
@@ -5546,11 +5838,11 @@ function frameOf(scene, index) {
|
|
|
5546
5838
|
candidatesAt: (beat) => {
|
|
5547
5839
|
const position = positionClass(beat, scene.plan.meters);
|
|
5548
5840
|
const chord = scene.timeline.at(beat);
|
|
5549
|
-
const tones = position === "strong" && chord !== null ?
|
|
5841
|
+
const tones = position === "strong" && chord !== null ? _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord) : null;
|
|
5550
5842
|
const scale = scaleAt(scene, beat);
|
|
5551
|
-
const candidates = position === "off" ? register : tones !== null ? register.filter((pitch) => tones.includes(
|
|
5843
|
+
const candidates = position === "off" ? register : tones !== null ? register.filter((pitch) => tones.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch))) : register.filter((pitch) => _chunkYDGMWH43cjs.isScaleTone.call(void 0, pitch, scale));
|
|
5552
5844
|
if (candidates.length === 0) {
|
|
5553
|
-
throw new (0,
|
|
5845
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(
|
|
5554
5846
|
`no ${position} pitch at beat ${beat} fits the register ${low}..${high}`,
|
|
5555
5847
|
{ at: phrase.startBeat }
|
|
5556
5848
|
);
|
|
@@ -5563,7 +5855,7 @@ function frameOf(scene, index) {
|
|
|
5563
5855
|
const target = targetPitch(phrase, beat);
|
|
5564
5856
|
return (pitch) => {
|
|
5565
5857
|
let cost = TARGET_COST * Math.abs(pitch - target);
|
|
5566
|
-
if (off && !
|
|
5858
|
+
if (off && !_chunkYDGMWH43cjs.isScaleTone.call(void 0, pitch, scale)) {
|
|
5567
5859
|
cost += OFF_SCALE_COST;
|
|
5568
5860
|
}
|
|
5569
5861
|
return cost + draw.float(0, TIE_BREAK, index, "tie", beat, pitch);
|
|
@@ -5582,7 +5874,7 @@ function membersOf(plan) {
|
|
|
5582
5874
|
}
|
|
5583
5875
|
});
|
|
5584
5876
|
return [...found].sort(
|
|
5585
|
-
(a, b) => (_nullishCoalesce(_optionalChain([plan, 'access',
|
|
5877
|
+
(a, b) => (_nullishCoalesce(_optionalChain([plan, 'access', _61 => _61.motifs, 'access', _62 => _62[a], 'optionalAccess', _63 => _63.startBeat]), () => ( 0))) - (_nullishCoalesce(_optionalChain([plan, 'access', _64 => _64.motifs, 'access', _65 => _65[b], 'optionalAccess', _66 => _66.startBeat]), () => ( 0))) || a - b
|
|
5586
5878
|
);
|
|
5587
5879
|
});
|
|
5588
5880
|
}
|
|
@@ -5595,13 +5887,13 @@ function segmentsOf(scene, index) {
|
|
|
5595
5887
|
if (motif === void 0) {
|
|
5596
5888
|
continue;
|
|
5597
5889
|
}
|
|
5598
|
-
if (motif.startBeat > cursor +
|
|
5890
|
+
if (motif.startBeat > cursor + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5599
5891
|
segments.push({ startBeat: cursor, endBeat: motif.startBeat, motif: null });
|
|
5600
5892
|
}
|
|
5601
5893
|
segments.push({ startBeat: motif.startBeat, endBeat: motif.endBeat, motif: m });
|
|
5602
5894
|
cursor = Math.max(cursor, motif.endBeat);
|
|
5603
5895
|
}
|
|
5604
|
-
if (phrase.endBeat > cursor +
|
|
5896
|
+
if (phrase.endBeat > cursor + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5605
5897
|
segments.push({ startBeat: cursor, endBeat: phrase.endBeat, motif: null });
|
|
5606
5898
|
}
|
|
5607
5899
|
return segments;
|
|
@@ -5616,29 +5908,30 @@ function notesAt(onsets, endBeat) {
|
|
|
5616
5908
|
function onsetSlots(scene, startBeat, endBeat) {
|
|
5617
5909
|
const { meters } = scene.plan;
|
|
5618
5910
|
const slots = [startBeat];
|
|
5619
|
-
let bar2 =
|
|
5620
|
-
while (bar2 < endBeat -
|
|
5621
|
-
const barEnd = bar2 +
|
|
5622
|
-
for (let k = 0; bar2 + k / RHYTHM_SUBDIVISION < barEnd -
|
|
5911
|
+
let bar2 = _chunkS3QELJUEcjs.barStartBeat.call(void 0, startBeat, meters);
|
|
5912
|
+
while (bar2 < endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5913
|
+
const barEnd = bar2 + _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, bar2, meters);
|
|
5914
|
+
for (let k = 0; bar2 + k / RHYTHM_SUBDIVISION < barEnd - _chunkS3QELJUEcjs.BEAT_EPS; k += 1) {
|
|
5623
5915
|
const beat = bar2 + k / RHYTHM_SUBDIVISION;
|
|
5624
|
-
if (beat > startBeat +
|
|
5916
|
+
if (beat > startBeat + _chunkS3QELJUEcjs.BEAT_EPS && beat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5625
5917
|
slots.push(beat);
|
|
5626
5918
|
}
|
|
5627
5919
|
}
|
|
5920
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, slots.length, "melody onset slots", scene.budget);
|
|
5628
5921
|
bar2 = barEnd;
|
|
5629
5922
|
}
|
|
5630
5923
|
return slots;
|
|
5631
5924
|
}
|
|
5632
5925
|
function drawOnsets(scene, phraseIndex, startBeat, endBeat, count) {
|
|
5633
5926
|
const slots = onsetSlots(scene, startBeat, endBeat);
|
|
5634
|
-
|
|
5927
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, slots.length * Math.max(1, count - 1), "melody onset slots", scene.budget);
|
|
5635
5928
|
if (count - 1 > slots.length - 1) {
|
|
5636
|
-
throw new (0,
|
|
5929
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(
|
|
5637
5930
|
`${count} onsets do not fit the sixteenth grid of beats ${startBeat}..${endBeat}`,
|
|
5638
5931
|
{ at: scene.plan.phrases[phraseIndex].startBeat }
|
|
5639
5932
|
);
|
|
5640
5933
|
}
|
|
5641
|
-
const levels = slots.map((beat) =>
|
|
5934
|
+
const levels = slots.map((beat) => _chunkLQZQDBCDcjs.rhythmLevel.call(void 0, beat, scene.plan.meters));
|
|
5642
5935
|
const perLevel = /* @__PURE__ */ new Map();
|
|
5643
5936
|
for (const level of levels) {
|
|
5644
5937
|
perLevel.set(level, (_nullishCoalesce(perLevel.get(level), () => ( 0))) + 1);
|
|
@@ -5653,7 +5946,7 @@ function drawOnsets(scene, phraseIndex, startBeat, endBeat, count) {
|
|
|
5653
5946
|
const last = slots.length - 1 - (count - 1 - k);
|
|
5654
5947
|
const candidates = [];
|
|
5655
5948
|
for (let j = current + 1; j <= last; j += 1) candidates.push(j);
|
|
5656
|
-
const gapShare = (j) => _nullishCoalesce(scene.plan.rhythm.interOnsetShares[
|
|
5949
|
+
const gapShare = (j) => _nullishCoalesce(scene.plan.rhythm.interOnsetShares[_chunkLQZQDBCDcjs.ioiBinIndex.call(void 0, slots[j] - slots[current])], () => ( 0));
|
|
5657
5950
|
let weights = candidates.map((j) => levelWeight[j] * gapShare(j));
|
|
5658
5951
|
if (!weights.some((w) => w > 0)) weights = candidates.map((j) => levelWeight[j]);
|
|
5659
5952
|
if (!weights.some((w) => w > 0)) weights = candidates.map(() => 1);
|
|
@@ -5691,7 +5984,7 @@ function searchedLine(rhythm, frame) {
|
|
|
5691
5984
|
}));
|
|
5692
5985
|
const pitches = searchPitches(slots, frame.budget);
|
|
5693
5986
|
if (pitches === null) {
|
|
5694
|
-
throw new (0,
|
|
5987
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(`no pitch line fits the register ${frame.low}..${frame.high}`, {
|
|
5695
5988
|
at: frame.at
|
|
5696
5989
|
});
|
|
5697
5990
|
}
|
|
@@ -5707,8 +6000,8 @@ function statementOf(scene, m) {
|
|
|
5707
6000
|
const frame = scene.frames[motif.phrase];
|
|
5708
6001
|
let notes;
|
|
5709
6002
|
if (motif.from === null) {
|
|
5710
|
-
if (motif.endBeat - motif.startBeat <=
|
|
5711
|
-
throw new (0,
|
|
6003
|
+
if (motif.endBeat - motif.startBeat <= _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6004
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(`root motif ${m} spans no time to place its notes in`, {
|
|
5712
6005
|
at: frame.at
|
|
5713
6006
|
});
|
|
5714
6007
|
}
|
|
@@ -5731,7 +6024,7 @@ function statementOf(scene, m) {
|
|
|
5731
6024
|
}
|
|
5732
6025
|
function freeNoteCount(scene, index, segment) {
|
|
5733
6026
|
const phrase = scene.plan.phrases[index];
|
|
5734
|
-
const bars =
|
|
6027
|
+
const bars = _chunkLQZQDBCDcjs.barSpanOf.call(void 0, segment.startBeat, segment.endBeat, scene.plan.meters);
|
|
5735
6028
|
return Math.max(1, Math.round(phrase.onsetDensity * bars));
|
|
5736
6029
|
}
|
|
5737
6030
|
function freeSpan(scene, index, segment) {
|
|
@@ -5754,7 +6047,7 @@ function freeSpan(scene, index, segment) {
|
|
|
5754
6047
|
function lineBefore(scene, index, beat) {
|
|
5755
6048
|
const line = [];
|
|
5756
6049
|
for (const segment of segmentsOf(scene, index)) {
|
|
5757
|
-
if (segment.endBeat > beat +
|
|
6050
|
+
if (segment.endBeat > beat + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5758
6051
|
break;
|
|
5759
6052
|
}
|
|
5760
6053
|
if (segment.motif === null) {
|
|
@@ -5765,22 +6058,13 @@ function lineBefore(scene, index, beat) {
|
|
|
5765
6058
|
}
|
|
5766
6059
|
return line.sort((a, b) => a.startBeat - b.startBeat);
|
|
5767
6060
|
}
|
|
5768
|
-
function finalDownbeat(scene, index) {
|
|
5769
|
-
const phrase = scene.plan.phrases[index];
|
|
5770
|
-
const { meters } = scene.plan;
|
|
5771
|
-
let downbeat = _chunkS5BKZZGMcjs.barStartBeat.call(void 0, phrase.startBeat, meters);
|
|
5772
|
-
while (downbeat + _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, downbeat, meters) < phrase.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS) {
|
|
5773
|
-
downbeat += _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, downbeat, meters);
|
|
5774
|
-
}
|
|
5775
|
-
return Math.max(downbeat, phrase.startBeat);
|
|
5776
|
-
}
|
|
5777
6061
|
function heldNoteIndex(scene, index, line, downbeat) {
|
|
5778
6062
|
const phrase = scene.plan.phrases[index];
|
|
5779
6063
|
const sounding2 = line.findIndex(
|
|
5780
|
-
(note2) => note2.startBeat <= downbeat +
|
|
6064
|
+
(note2) => note2.startBeat <= downbeat + _chunkS3QELJUEcjs.BEAT_EPS && note2.startBeat + note2.durationBeat > downbeat + _chunkS3QELJUEcjs.BEAT_EPS
|
|
5781
6065
|
);
|
|
5782
6066
|
return sounding2 >= 0 ? sounding2 : line.findIndex(
|
|
5783
|
-
(note2) => note2.startBeat >= downbeat -
|
|
6067
|
+
(note2) => note2.startBeat >= downbeat - _chunkS3QELJUEcjs.BEAT_EPS && note2.startBeat < phrase.endBeat - _chunkS3QELJUEcjs.BEAT_EPS
|
|
5784
6068
|
);
|
|
5785
6069
|
}
|
|
5786
6070
|
function repairCadence(scene, index, line, held) {
|
|
@@ -5804,15 +6088,15 @@ function repairCadence(scene, index, line, held) {
|
|
|
5804
6088
|
}
|
|
5805
6089
|
const frame = scene.frames[index];
|
|
5806
6090
|
const candidates = registerPitches(phrase).filter(
|
|
5807
|
-
(pitch) => allowed.includes(
|
|
6091
|
+
(pitch) => allowed.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch))
|
|
5808
6092
|
);
|
|
5809
6093
|
if (candidates.length === 0) {
|
|
5810
|
-
throw new (0,
|
|
6094
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(
|
|
5811
6095
|
`no pitch in the register ${frame.low}..${frame.high} can end the ${phrase.cadence} cadence`,
|
|
5812
6096
|
{ at: frame.at }
|
|
5813
6097
|
);
|
|
5814
6098
|
}
|
|
5815
|
-
if (allowed.includes(
|
|
6099
|
+
if (allowed.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, note2.pitch))) {
|
|
5816
6100
|
return;
|
|
5817
6101
|
}
|
|
5818
6102
|
const slots = line.map(
|
|
@@ -5820,7 +6104,7 @@ function repairCadence(scene, index, line, held) {
|
|
|
5820
6104
|
);
|
|
5821
6105
|
const pitches = searchPitches(slots, frame.budget);
|
|
5822
6106
|
if (pitches === null) {
|
|
5823
|
-
throw new (0,
|
|
6107
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(`no cadence pitch joins its neighbours without an augmented step`, {
|
|
5824
6108
|
at: frame.at
|
|
5825
6109
|
});
|
|
5826
6110
|
}
|
|
@@ -5829,7 +6113,7 @@ function repairCadence(scene, index, line, held) {
|
|
|
5829
6113
|
function repickCutOnset(scene, index, line, held) {
|
|
5830
6114
|
const note2 = line[held];
|
|
5831
6115
|
const derived = scene.plan.motifs.some(
|
|
5832
|
-
(motif) => motif.from !== null && note2.startBeat >= motif.startBeat -
|
|
6116
|
+
(motif) => motif.from !== null && note2.startBeat >= motif.startBeat - _chunkS3QELJUEcjs.BEAT_EPS && note2.startBeat < motif.endBeat - _chunkS3QELJUEcjs.BEAT_EPS
|
|
5833
6117
|
);
|
|
5834
6118
|
if (scene.plan.phrases[index].cadence !== null || derived) {
|
|
5835
6119
|
return;
|
|
@@ -5844,7 +6128,7 @@ function repickCutOnset(scene, index, line, held) {
|
|
|
5844
6128
|
);
|
|
5845
6129
|
const pitches = searchPitches(slots, frame.budget);
|
|
5846
6130
|
if (pitches === null) {
|
|
5847
|
-
throw new (0,
|
|
6131
|
+
throw new (0, _chunkS3QELJUEcjs.NoSolutionError)(`no pitch at the final downbeat joins its neighbours`, {
|
|
5848
6132
|
at: frame.at
|
|
5849
6133
|
});
|
|
5850
6134
|
}
|
|
@@ -5877,13 +6161,13 @@ function chargePitchSearch(scene) {
|
|
|
5877
6161
|
const register = Math.max(0, phrase.register.high - phrase.register.low + 1);
|
|
5878
6162
|
estimate += searched * SEARCH_STATES_SQUARED * register * register;
|
|
5879
6163
|
});
|
|
5880
|
-
|
|
6164
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, estimate, "melody pitch search", scene.budget);
|
|
5881
6165
|
}
|
|
5882
6166
|
function generateMelody(plan, opts) {
|
|
5883
6167
|
assertCompositionPlan(plan);
|
|
5884
|
-
const asked =
|
|
6168
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
5885
6169
|
if (asked.budget !== void 0) {
|
|
5886
|
-
|
|
6170
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, asked.budget, "budget", Number.MAX_SAFE_INTEGER);
|
|
5887
6171
|
}
|
|
5888
6172
|
const timeline = planChordTimeline(plan);
|
|
5889
6173
|
const scene = {
|
|
@@ -5892,7 +6176,7 @@ function generateMelody(plan, opts) {
|
|
|
5892
6176
|
budget: asked.budget,
|
|
5893
6177
|
timeline,
|
|
5894
6178
|
harmonyMisfits: planHarmonyMisfits(plan, timeline),
|
|
5895
|
-
scales: plan.keys.map((key) =>
|
|
6179
|
+
scales: plan.keys.map((key) => _chunkYDGMWH43cjs.scaleOf.call(void 0, key)),
|
|
5896
6180
|
members: membersOf(plan),
|
|
5897
6181
|
frames: [],
|
|
5898
6182
|
statements: /* @__PURE__ */ new Map(),
|
|
@@ -5904,12 +6188,12 @@ function generateMelody(plan, opts) {
|
|
|
5904
6188
|
const melody = [];
|
|
5905
6189
|
plan.phrases.forEach((_, index) => {
|
|
5906
6190
|
const line = phraseLine(scene, index);
|
|
5907
|
-
const downbeat = finalDownbeat(
|
|
6191
|
+
const downbeat = finalDownbeat(plan.phrases[index], plan.meters);
|
|
5908
6192
|
let held = heldNoteIndex(scene, index, line, downbeat);
|
|
5909
6193
|
if (held >= 0) {
|
|
5910
6194
|
line.length = held + 1;
|
|
5911
6195
|
const note2 = line[held];
|
|
5912
|
-
if (note2.startBeat < downbeat -
|
|
6196
|
+
if (note2.startBeat < downbeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
5913
6197
|
const cut = downbeat - note2.startBeat;
|
|
5914
6198
|
line[held] = { ...note2, durationBeat: cut };
|
|
5915
6199
|
line.push({ ...note2, startBeat: downbeat, durationBeat: note2.durationBeat - cut });
|
|
@@ -5940,8 +6224,8 @@ var DEFAULT_VELOCITY2 = 80;
|
|
|
5940
6224
|
var MIN_VELOCITY2 = 1;
|
|
5941
6225
|
var MAX_VELOCITY2 = 127;
|
|
5942
6226
|
var SLIDE_MIN_SEMITONES = 1;
|
|
5943
|
-
function eligible(style, note2, previous, next,
|
|
5944
|
-
const strong =
|
|
6227
|
+
function eligible(style, note2, previous, next, meter) {
|
|
6228
|
+
const strong = _chunkS3QELJUEcjs.isStrongBeat.call(void 0, note2.startBeat, meter);
|
|
5945
6229
|
switch (style) {
|
|
5946
6230
|
case "ghost":
|
|
5947
6231
|
return !strong;
|
|
@@ -5949,7 +6233,7 @@ function eligible(style, note2, previous, next, ts) {
|
|
|
5949
6233
|
case "accent":
|
|
5950
6234
|
return strong;
|
|
5951
6235
|
case "drag":
|
|
5952
|
-
return !strong && next !== void 0 &&
|
|
6236
|
+
return !strong && next !== void 0 && _chunkS3QELJUEcjs.isStrongBeat.call(void 0, next.startBeat, meter);
|
|
5953
6237
|
case "slide":
|
|
5954
6238
|
return previous !== void 0 && Math.abs(note2.pitch - previous.pitch) >= SLIDE_MIN_SEMITONES;
|
|
5955
6239
|
}
|
|
@@ -5974,25 +6258,24 @@ function clampVelocity(velocity) {
|
|
|
5974
6258
|
return Math.min(MAX_VELOCITY2, Math.max(MIN_VELOCITY2, Math.round(velocity)));
|
|
5975
6259
|
}
|
|
5976
6260
|
function ornament(notes, opts = {}) {
|
|
5977
|
-
const asked =
|
|
5978
|
-
|
|
5979
|
-
const style =
|
|
5980
|
-
const
|
|
5981
|
-
_chunkS5BKZZGMcjs.assertTimeSignature.call(void 0, ts);
|
|
6261
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
6262
|
+
_chunkS3QELJUEcjs.assertNoteEvents.call(void 0, notes, "ornament notes", { allowNonPositiveDuration: true });
|
|
6263
|
+
const style = _chunkS3QELJUEcjs.assertOneOf.call(void 0, _nullishCoalesce(asked.style, () => ( DEFAULT_STYLE2)), ORNAMENT_STYLES, "ornament style");
|
|
6264
|
+
const meter = _chunkS3QELJUEcjs.toMeterData.call(void 0, _nullishCoalesce(asked.ts, () => ( DEFAULT_TS5)), "ts");
|
|
5982
6265
|
if (asked.amount !== void 0) {
|
|
5983
|
-
|
|
6266
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, asked.amount, 0, 1, "ornament amount");
|
|
5984
6267
|
}
|
|
5985
6268
|
const ctx = resolveContextWith(asked.ctx, { ornament: asked.amount });
|
|
5986
6269
|
const amount = _nullishCoalesce(ctx.ornament, () => ( DEFAULT_AMOUNT));
|
|
5987
6270
|
const draw = ctx.part("ornament");
|
|
5988
|
-
const sounding2 =
|
|
6271
|
+
const sounding2 = _chunkS3QELJUEcjs.dropSilentNotes.call(void 0, notes);
|
|
5989
6272
|
const ordered = [...sounding2].sort((a, b) => a.startBeat - b.startBeat || a.pitch - b.pitch);
|
|
5990
6273
|
const previousOf = previousOnsets(ordered);
|
|
5991
6274
|
const nextOf = nextOnsets(ordered);
|
|
5992
6275
|
const gaps = strokeGaps(ordered);
|
|
5993
6276
|
return sounding2.map((note2) => {
|
|
5994
6277
|
const decorated = { ...note2 };
|
|
5995
|
-
if (note2.articulation !== void 0 || !eligible(style, note2, previousOf.get(note2), nextOf.get(note2),
|
|
6278
|
+
if (note2.articulation !== void 0 || !eligible(style, note2, previousOf.get(note2), nextOf.get(note2), meter)) {
|
|
5996
6279
|
return decorated;
|
|
5997
6280
|
}
|
|
5998
6281
|
if (!sustainsStrokes(_nullishCoalesce(gaps.get(note2), () => ( Number.POSITIVE_INFINITY)), ctx.bpm, ctx.difficulty)) {
|
|
@@ -6081,20 +6364,20 @@ function lerp(weight, reference, neutral) {
|
|
|
6081
6364
|
return weight * reference + (1 - weight) * neutral;
|
|
6082
6365
|
}
|
|
6083
6366
|
function readPreserve(value) {
|
|
6084
|
-
const read = value === void 0 ? {} :
|
|
6367
|
+
const read = value === void 0 ? {} : _chunkS3QELJUEcjs.assertRecord.call(void 0, value, "opts.preserve");
|
|
6085
6368
|
const weights = {};
|
|
6086
6369
|
for (const aspect of PRESERVE_ASPECTS) {
|
|
6087
6370
|
const weight = read[aspect];
|
|
6088
|
-
weights[aspect] = weight === void 0 ? 1 :
|
|
6371
|
+
weights[aspect] = weight === void 0 ? 1 : _chunkS3QELJUEcjs.assertRange.call(void 0, weight, 0, 1, `opts.preserve.${aspect}`);
|
|
6089
6372
|
}
|
|
6090
6373
|
return weights;
|
|
6091
6374
|
}
|
|
6092
6375
|
function readRegister(value) {
|
|
6093
|
-
const read =
|
|
6094
|
-
const low =
|
|
6095
|
-
const high =
|
|
6376
|
+
const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, "opts.register");
|
|
6377
|
+
const low = _chunkS3QELJUEcjs.assertMidiPitch.call(void 0, read.low, "opts.register.low");
|
|
6378
|
+
const high = _chunkS3QELJUEcjs.assertMidiPitch.call(void 0, read.high, "opts.register.high");
|
|
6096
6379
|
if (low > high) {
|
|
6097
|
-
throw new (0,
|
|
6380
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
6098
6381
|
`opts.register.low must not exceed opts.register.high; received ${low} > ${high}`
|
|
6099
6382
|
);
|
|
6100
6383
|
}
|
|
@@ -6102,30 +6385,31 @@ function readRegister(value) {
|
|
|
6102
6385
|
}
|
|
6103
6386
|
function rejectSuppliedRng(ctx) {
|
|
6104
6387
|
if (typeof ctx === "object" && ctx !== null && ctx.rng !== void 0) {
|
|
6105
|
-
throw new (0,
|
|
6388
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
6106
6389
|
"opts.ctx.rng is not accepted: a composition plan records its seed, not a source"
|
|
6107
6390
|
);
|
|
6108
6391
|
}
|
|
6109
6392
|
}
|
|
6110
6393
|
function plannedKeys(profile, requested) {
|
|
6111
|
-
const regions = profile.harmony.keys.map(
|
|
6112
|
-
(
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6394
|
+
const regions = profile.harmony.keys.map(({ key }) => {
|
|
6395
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, key);
|
|
6396
|
+
return {
|
|
6397
|
+
scale: { ...resolved.scale },
|
|
6398
|
+
tonic: { ...resolved.tonic },
|
|
6399
|
+
variant: resolved.variant
|
|
6400
|
+
};
|
|
6401
|
+
});
|
|
6118
6402
|
const home = regions[0];
|
|
6119
6403
|
if (requested === void 0) {
|
|
6120
6404
|
return regions;
|
|
6121
6405
|
}
|
|
6122
|
-
const target =
|
|
6406
|
+
const target = _chunkYDGMWH43cjs.resolveKey.call(void 0, requested);
|
|
6123
6407
|
if (target.variant !== home.variant || target.scale.modeMask12 !== home.scale.modeMask12) {
|
|
6124
|
-
throw new (0,
|
|
6408
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
6125
6409
|
"opts.key must be in the same mode as the reference's home key; a key change moves the tonic only"
|
|
6126
6410
|
);
|
|
6127
6411
|
}
|
|
6128
|
-
const step =
|
|
6412
|
+
const step = _chunkS3QELJUEcjs.spelledInterval.call(void 0,
|
|
6129
6413
|
{ letter: home.tonic.letter, alter: home.tonic.alter },
|
|
6130
6414
|
{ letter: target.tonic.letter, alter: target.tonic.alter }
|
|
6131
6415
|
);
|
|
@@ -6135,7 +6419,7 @@ function plannedKeys(profile, requested) {
|
|
|
6135
6419
|
rootPc: mod12(key.scale.rootPc + step.semitones),
|
|
6136
6420
|
modeMask12: key.scale.modeMask12
|
|
6137
6421
|
},
|
|
6138
|
-
tonic:
|
|
6422
|
+
tonic: _chunkS3QELJUEcjs.transposeByInterval.call(void 0, { letter: key.tonic.letter, alter: key.tonic.alter }, step),
|
|
6139
6423
|
variant: key.variant
|
|
6140
6424
|
})
|
|
6141
6425
|
);
|
|
@@ -6147,7 +6431,7 @@ function nearestBoundary(beat, boundaries) {
|
|
|
6147
6431
|
let bestDistance = Number.POSITIVE_INFINITY;
|
|
6148
6432
|
for (const boundary of boundaries) {
|
|
6149
6433
|
const distance = Math.abs(boundary - beat);
|
|
6150
|
-
if (distance < bestDistance -
|
|
6434
|
+
if (distance < bestDistance - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6151
6435
|
best = boundary;
|
|
6152
6436
|
bestDistance = distance;
|
|
6153
6437
|
}
|
|
@@ -6167,9 +6451,9 @@ function plannedSections(profile, weight, draw) {
|
|
|
6167
6451
|
const neighbour = index + 1 < sections.length ? index + 1 : index - 1;
|
|
6168
6452
|
const startBeat = nearestBoundary(section.startBeat, boundaries);
|
|
6169
6453
|
const endBeat = nearestBoundary(section.endBeat, boundaries);
|
|
6170
|
-
if (endBeat - startBeat >
|
|
6454
|
+
if (endBeat - startBeat > _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6171
6455
|
planned.push({
|
|
6172
|
-
label: keep ? section.label : _nullishCoalesce(_optionalChain([sections, 'access',
|
|
6456
|
+
label: keep ? section.label : _nullishCoalesce(_optionalChain([sections, 'access', _67 => _67[neighbour], 'optionalAccess', _68 => _68.label]), () => ( section.label)),
|
|
6173
6457
|
startBeat,
|
|
6174
6458
|
endBeat
|
|
6175
6459
|
});
|
|
@@ -6180,9 +6464,9 @@ function plannedSections(profile, weight, draw) {
|
|
|
6180
6464
|
function beatAfterBars(startBeat, bars, meters) {
|
|
6181
6465
|
let beat = startBeat;
|
|
6182
6466
|
let left = bars;
|
|
6183
|
-
while (left >
|
|
6467
|
+
while (left > _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6184
6468
|
const step = Math.min(1, left);
|
|
6185
|
-
beat += step *
|
|
6469
|
+
beat += step * _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, beat, meters);
|
|
6186
6470
|
left -= step;
|
|
6187
6471
|
}
|
|
6188
6472
|
return beat;
|
|
@@ -6190,9 +6474,9 @@ function beatAfterBars(startBeat, bars, meters) {
|
|
|
6190
6474
|
function barsBetween(startBeat, endBeat, meters) {
|
|
6191
6475
|
let beat = startBeat;
|
|
6192
6476
|
let bars = 0;
|
|
6193
|
-
while (beat < endBeat -
|
|
6194
|
-
const barBeats =
|
|
6195
|
-
const step = Math.min(
|
|
6477
|
+
while (beat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6478
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBarAt.call(void 0, beat, meters);
|
|
6479
|
+
const step = Math.min(_chunkS3QELJUEcjs.barStartBeat.call(void 0, beat, meters) + barBeats, endBeat) - beat;
|
|
6196
6480
|
bars += step / barBeats;
|
|
6197
6481
|
beat += step;
|
|
6198
6482
|
}
|
|
@@ -6203,7 +6487,7 @@ function spanSegments(profile, sections) {
|
|
|
6203
6487
|
const cuts = [startBeat, endBeat];
|
|
6204
6488
|
for (const section of sections) {
|
|
6205
6489
|
for (const beat of [section.startBeat, section.endBeat]) {
|
|
6206
|
-
if (beat > startBeat +
|
|
6490
|
+
if (beat > startBeat + _chunkS3QELJUEcjs.BEAT_EPS && beat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS) cuts.push(beat);
|
|
6207
6491
|
}
|
|
6208
6492
|
}
|
|
6209
6493
|
cuts.sort((a, b) => a - b);
|
|
@@ -6211,7 +6495,7 @@ function spanSegments(profile, sections) {
|
|
|
6211
6495
|
for (let index = 1; index < cuts.length; index += 1) {
|
|
6212
6496
|
const from = cuts[index - 1];
|
|
6213
6497
|
const to = cuts[index];
|
|
6214
|
-
if (to - from >
|
|
6498
|
+
if (to - from > _chunkS3QELJUEcjs.BEAT_EPS) segments.push([from, to]);
|
|
6215
6499
|
}
|
|
6216
6500
|
return segments;
|
|
6217
6501
|
}
|
|
@@ -6221,13 +6505,13 @@ function plannedPhraseSpans(profile, sections, weight, draw) {
|
|
|
6221
6505
|
startBeat: phrase.startBeat,
|
|
6222
6506
|
endBeat: phrase.endBeat,
|
|
6223
6507
|
source,
|
|
6224
|
-
cadence: _nullishCoalesce(_optionalChain([phrase, 'access',
|
|
6508
|
+
cadence: _nullishCoalesce(_optionalChain([phrase, 'access', _69 => _69.cadence, 'optionalAccess', _70 => _70.type]), () => ( null))
|
|
6225
6509
|
}));
|
|
6226
6510
|
const replaced = pieces.map((_, index) => !draw.prob(weight, "phraseLengths", index));
|
|
6227
6511
|
const spans = [];
|
|
6228
6512
|
for (const [segmentStart, segmentEnd] of segments) {
|
|
6229
6513
|
const members = pieces.map((piece, index) => ({ piece, index })).filter(
|
|
6230
|
-
({ piece }) => piece.startBeat >= segmentStart -
|
|
6514
|
+
({ piece }) => piece.startBeat >= segmentStart - _chunkS3QELJUEcjs.BEAT_EPS && piece.startBeat < segmentEnd - _chunkS3QELJUEcjs.BEAT_EPS
|
|
6231
6515
|
);
|
|
6232
6516
|
const laid = [];
|
|
6233
6517
|
let cursor = segmentStart;
|
|
@@ -6236,7 +6520,7 @@ function plannedPhraseSpans(profile, sections, weight, draw) {
|
|
|
6236
6520
|
if (replaced[index]) {
|
|
6237
6521
|
const bars = barsBetween(piece.startBeat, piece.endBeat, profile.meters);
|
|
6238
6522
|
const rounded = 2 ** Math.round(Math.log2(bars));
|
|
6239
|
-
const overflows = beatAfterBars(cursor, rounded, profile.meters) > segmentEnd +
|
|
6523
|
+
const overflows = beatAfterBars(cursor, rounded, profile.meters) > segmentEnd + _chunkS3QELJUEcjs.BEAT_EPS;
|
|
6240
6524
|
let partStart = cursor;
|
|
6241
6525
|
for (const part of overflows ? [rounded / 2, rounded / 2] : [rounded]) {
|
|
6242
6526
|
const partEnd = beatAfterBars(partStart, part, profile.meters);
|
|
@@ -6247,7 +6531,7 @@ function plannedPhraseSpans(profile, sections, weight, draw) {
|
|
|
6247
6531
|
lengths.push(piece.endBeat - piece.startBeat);
|
|
6248
6532
|
}
|
|
6249
6533
|
lengths.forEach((length, part) => {
|
|
6250
|
-
if (cursor >= segmentEnd -
|
|
6534
|
+
if (cursor >= segmentEnd - _chunkS3QELJUEcjs.BEAT_EPS) return;
|
|
6251
6535
|
const end = cursor + length;
|
|
6252
6536
|
laid.push({
|
|
6253
6537
|
startBeat: cursor,
|
|
@@ -6265,7 +6549,7 @@ function plannedPhraseSpans(profile, sections, weight, draw) {
|
|
|
6265
6549
|
laid.push({
|
|
6266
6550
|
startBeat: segmentStart,
|
|
6267
6551
|
endBeat: segmentEnd,
|
|
6268
|
-
source: _nullishCoalesce(_optionalChain([spans, 'access',
|
|
6552
|
+
source: _nullishCoalesce(_optionalChain([spans, 'access', _71 => _71.at, 'call', _72 => _72(-1), 'optionalAccess', _73 => _73.source]), () => ( (profile.form.phrases.length > 0 ? 0 : -1))),
|
|
6269
6553
|
cadence: null
|
|
6270
6554
|
});
|
|
6271
6555
|
}
|
|
@@ -6275,13 +6559,13 @@ function plannedPhraseSpans(profile, sections, weight, draw) {
|
|
|
6275
6559
|
}
|
|
6276
6560
|
function sectionAt(sections, beat) {
|
|
6277
6561
|
const index = sections.findIndex(
|
|
6278
|
-
(section) => beat >= section.startBeat -
|
|
6562
|
+
(section) => beat >= section.startBeat - _chunkS3QELJUEcjs.BEAT_EPS && beat < section.endBeat - _chunkS3QELJUEcjs.BEAT_EPS
|
|
6279
6563
|
);
|
|
6280
6564
|
return index < 0 ? null : index;
|
|
6281
6565
|
}
|
|
6282
6566
|
function phraseHolding(phrases, startBeat, endBeat) {
|
|
6283
6567
|
return phrases.findIndex(
|
|
6284
|
-
(phrase) => startBeat >= phrase.startBeat -
|
|
6568
|
+
(phrase) => startBeat >= phrase.startBeat - _chunkS3QELJUEcjs.BEAT_EPS && endBeat <= phrase.endBeat + _chunkS3QELJUEcjs.BEAT_EPS
|
|
6285
6569
|
);
|
|
6286
6570
|
}
|
|
6287
6571
|
function better(a, b) {
|
|
@@ -6298,7 +6582,7 @@ function scheduleMotifs(candidates, meters) {
|
|
|
6298
6582
|
let high = count;
|
|
6299
6583
|
while (low < high) {
|
|
6300
6584
|
const mid = low + high >> 1;
|
|
6301
|
-
if (order[mid].startBeat < beat -
|
|
6585
|
+
if (order[mid].startBeat < beat - _chunkS3QELJUEcjs.BEAT_EPS) low = mid + 1;
|
|
6302
6586
|
else high = mid;
|
|
6303
6587
|
}
|
|
6304
6588
|
return low;
|
|
@@ -6307,7 +6591,7 @@ function scheduleMotifs(candidates, meters) {
|
|
|
6307
6591
|
const own = order.map(
|
|
6308
6592
|
(candidate) => [
|
|
6309
6593
|
candidate.notes,
|
|
6310
|
-
|
|
6594
|
+
_chunkS3QELJUEcjs.metricWeight.call(void 0, candidate.startBeat, meters) < STRONG_WEIGHT2 ? -1 : 0,
|
|
6311
6595
|
1
|
|
6312
6596
|
]
|
|
6313
6597
|
);
|
|
@@ -6341,8 +6625,8 @@ function selectedDerivation(graph, parentEdge, selectedAt, node) {
|
|
|
6341
6625
|
for (let edge = parentEdge.get(node); edge !== void 0; edge = parentEdge.get(edge.from)) {
|
|
6342
6626
|
const relation = edge.relation;
|
|
6343
6627
|
steps += 1;
|
|
6344
|
-
plain &&= relation !== null && (relation.kind === "repetition" || relation.kind === "transposition" && Math.abs(relation.timeRatio - 1) <=
|
|
6345
|
-
semitones += _nullishCoalesce(_optionalChain([relation, 'optionalAccess',
|
|
6628
|
+
plain &&= relation !== null && (relation.kind === "repetition" || relation.kind === "transposition" && Math.abs(relation.timeRatio - 1) <= _chunkS3QELJUEcjs.BEAT_EPS);
|
|
6629
|
+
semitones += _nullishCoalesce(_optionalChain([relation, 'optionalAccess', _74 => _74.semitones]), () => ( 0));
|
|
6346
6630
|
const from = selectedAt.get(edge.from);
|
|
6347
6631
|
if (from === void 0) continue;
|
|
6348
6632
|
if (steps === 1) {
|
|
@@ -6351,12 +6635,12 @@ function selectedDerivation(graph, parentEdge, selectedAt, node) {
|
|
|
6351
6635
|
if (!plain) {
|
|
6352
6636
|
return { from: null, relation: null };
|
|
6353
6637
|
}
|
|
6354
|
-
const gap = (_nullishCoalesce(_optionalChain([graph, 'access',
|
|
6638
|
+
const gap = (_nullishCoalesce(_optionalChain([graph, 'access', _75 => _75.nodes, 'access', _76 => _76[node], 'optionalAccess', _77 => _77.startBeat]), () => ( 0))) - (_nullishCoalesce(_optionalChain([graph, 'access', _78 => _78.nodes, 'access', _79 => _79[edge.from], 'optionalAccess', _80 => _80.endBeat]), () => ( 0)));
|
|
6355
6639
|
return {
|
|
6356
6640
|
from,
|
|
6357
6641
|
relation: {
|
|
6358
6642
|
kind: semitones === 0 ? "repetition" : "transposition",
|
|
6359
|
-
sequence: gap >= -
|
|
6643
|
+
sequence: gap >= -_chunkLQZQDBCDcjs.HUMANIZE_ADJACENCY && gap <= _chunkLQZQDBCDcjs.HUMANIZE_ADJACENCY,
|
|
6360
6644
|
semitones,
|
|
6361
6645
|
timeRatio: 1
|
|
6362
6646
|
}
|
|
@@ -6364,11 +6648,23 @@ function selectedDerivation(graph, parentEdge, selectedAt, node) {
|
|
|
6364
6648
|
}
|
|
6365
6649
|
return { from: null, relation: null };
|
|
6366
6650
|
}
|
|
6651
|
+
function functionTriad(fn, degree, key) {
|
|
6652
|
+
if (fn === "dominant" && _chunkYDGMWH43cjs.cadencesThroughRaisedSeventh.call(void 0, key.scale)) {
|
|
6653
|
+
if (degree === 5) {
|
|
6654
|
+
return _chunkYDGMWH43cjs.makeChord.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.scale.rootPc + 7), "maj");
|
|
6655
|
+
}
|
|
6656
|
+
if (degree === 7) {
|
|
6657
|
+
return _chunkYDGMWH43cjs.makeChord.call(void 0, _chunkYDGMWH43cjs.leadingTonePcOf.call(void 0, key.scale), "dim");
|
|
6658
|
+
}
|
|
6659
|
+
}
|
|
6660
|
+
return _chunkYDGMWH43cjs.diatonicTriad.call(void 0, degree, key);
|
|
6661
|
+
}
|
|
6367
6662
|
function functionCandidates(fn, key) {
|
|
6368
|
-
if (
|
|
6663
|
+
if (_chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, key).length !== HEPTATONIC_DEGREES) {
|
|
6369
6664
|
return null;
|
|
6370
6665
|
}
|
|
6371
|
-
|
|
6666
|
+
const numerals = FUNCTION_DEGREES[fn].map((degree) => functionTriad(fn, degree, key)).filter((chord) => _chunkLQZQDBCDcjs.functionOf.call(void 0, chord, key) === fn).map((chord) => _chunkLQZQDBCDcjs.chordToRoman.call(void 0, chord, key));
|
|
6667
|
+
return numerals.length === 0 ? null : numerals;
|
|
6372
6668
|
}
|
|
6373
6669
|
function plannedHarmony(profile, keys, preserve, draw) {
|
|
6374
6670
|
const chords = profile.harmony.chords;
|
|
@@ -6386,7 +6682,7 @@ function plannedHarmony(profile, keys, preserve, draw) {
|
|
|
6386
6682
|
const starts = [];
|
|
6387
6683
|
chords.forEach((chord, index) => {
|
|
6388
6684
|
const keep = index === 0 || draw.prob(preserve.harmonicRhythm, "harmonicRhythm", index);
|
|
6389
|
-
const start = keep ? chord.startBeat :
|
|
6685
|
+
const start = keep ? chord.startBeat : _chunkS3QELJUEcjs.barStartBeat.call(void 0, chord.startBeat, profile.meters);
|
|
6390
6686
|
starts.push(index === 0 ? start : Math.max(start, starts[index - 1]));
|
|
6391
6687
|
});
|
|
6392
6688
|
const planned = [];
|
|
@@ -6395,10 +6691,10 @@ function plannedHarmony(profile, keys, preserve, draw) {
|
|
|
6395
6691
|
const nextStart = starts[index + 1];
|
|
6396
6692
|
let endBeat = chord.endBeat;
|
|
6397
6693
|
if (next !== void 0 && nextStart !== void 0) {
|
|
6398
|
-
endBeat = Math.abs(chord.endBeat - next.startBeat) <=
|
|
6694
|
+
endBeat = Math.abs(chord.endBeat - next.startBeat) <= _chunkS3QELJUEcjs.BEAT_EPS ? nextStart : Math.min(chord.endBeat, nextStart);
|
|
6399
6695
|
}
|
|
6400
6696
|
const startBeat = starts[index];
|
|
6401
|
-
if (endBeat - startBeat >
|
|
6697
|
+
if (endBeat - startBeat > _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6402
6698
|
planned.push({ startBeat, endBeat, key: chord.key, roman: romans[index] });
|
|
6403
6699
|
}
|
|
6404
6700
|
});
|
|
@@ -6415,8 +6711,8 @@ function plannedRhythm(profile, weight) {
|
|
|
6415
6711
|
};
|
|
6416
6712
|
}
|
|
6417
6713
|
function deriveCompositionPlan(reference, opts) {
|
|
6418
|
-
const profile =
|
|
6419
|
-
const asked =
|
|
6714
|
+
const profile = _chunkLQZQDBCDcjs.assertReferenceProfile.call(void 0, reference, "reference");
|
|
6715
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
6420
6716
|
const preserve = readPreserve(asked.preserve);
|
|
6421
6717
|
const requestedRegister = asked.register === void 0 ? void 0 : readRegister(asked.register);
|
|
6422
6718
|
rejectSuppliedRng(asked.ctx);
|
|
@@ -6424,16 +6720,16 @@ function deriveCompositionPlan(reference, opts) {
|
|
|
6424
6720
|
const draw = ctx.part("plan");
|
|
6425
6721
|
const melodyRegister = profile.melody.register;
|
|
6426
6722
|
if (profile.melody.rhythm.onsets === 0 || melodyRegister === null) {
|
|
6427
|
-
throw new (0,
|
|
6723
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("reference must carry melody onsets to derive a plan from");
|
|
6428
6724
|
}
|
|
6429
6725
|
const keys = plannedKeys(profile, asked.key);
|
|
6430
6726
|
const homeShift = mod12(
|
|
6431
|
-
keys[0].scale.rootPc - (_nullishCoalesce(_optionalChain([profile, 'access',
|
|
6727
|
+
keys[0].scale.rootPc - (_nullishCoalesce(_optionalChain([profile, 'access', _81 => _81.harmony, 'access', _82 => _82.keys, 'access', _83 => _83[0], 'optionalAccess', _84 => _84.key, 'access', _85 => _85.scale, 'access', _86 => _86.rootPc]), () => ( 0)))
|
|
6432
6728
|
);
|
|
6433
6729
|
const shift = homeShift >= 6 ? homeShift - 12 : homeShift;
|
|
6434
6730
|
const source = { low: melodyRegister.low + shift, high: melodyRegister.high + shift };
|
|
6435
6731
|
if (source.low < 0 || source.high > 127) {
|
|
6436
|
-
throw new (0,
|
|
6732
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
6437
6733
|
`the reference melody range moved to the new key leaves the MIDI range; received ${source.low}..${source.high}`
|
|
6438
6734
|
);
|
|
6439
6735
|
}
|
|
@@ -6448,9 +6744,14 @@ function deriveCompositionPlan(reference, opts) {
|
|
|
6448
6744
|
};
|
|
6449
6745
|
const sections = plannedSections(profile, preserve.form, draw);
|
|
6450
6746
|
const shapeWeight = preserve.registerShape;
|
|
6747
|
+
const phraseBars = profile.form.phrases.reduce(
|
|
6748
|
+
(bars, phrase) => bars + _chunkS3QELJUEcjs.barIndexAt.call(void 0, phrase.endBeat, profile.meters) - _chunkS3QELJUEcjs.barIndexAt.call(void 0, phrase.startBeat, profile.meters),
|
|
6749
|
+
0
|
|
6750
|
+
);
|
|
6751
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, phraseBars, "plan phrase bars");
|
|
6451
6752
|
const spans = plannedPhraseSpans(profile, sections, preserve.phraseLengths, draw);
|
|
6452
6753
|
const phrases = spans.map((span) => {
|
|
6453
|
-
const melody = _nullishCoalesce(_optionalChain([profile, 'access',
|
|
6754
|
+
const melody = _nullishCoalesce(_optionalChain([profile, 'access', _87 => _87.form, 'access', _88 => _88.phrases, 'access', _89 => _89[span.source], 'optionalAccess', _90 => _90.melody]), () => ( null));
|
|
6454
6755
|
const register = melody ? {
|
|
6455
6756
|
low: Math.round(lerp(shapeWeight, mapPitch(melody.low), neutralRegister.low)),
|
|
6456
6757
|
high: Math.round(lerp(shapeWeight, mapPitch(melody.high), neutralRegister.high)),
|
|
@@ -6469,8 +6770,8 @@ function deriveCompositionPlan(reference, opts) {
|
|
|
6469
6770
|
};
|
|
6470
6771
|
});
|
|
6471
6772
|
const graph = profile.melody.graph;
|
|
6472
|
-
const noteCount = (node) => (_nullishCoalesce(_optionalChain([profile, 'access',
|
|
6473
|
-
|
|
6773
|
+
const noteCount = (node) => (_nullishCoalesce(_optionalChain([profile, 'access', _91 => _91.melody, 'access', _92 => _92.motifs, 'access', _93 => _93[_nullishCoalesce(_optionalChain([graph, 'access', _94 => _94.nodes, 'access', _95 => _95[node], 'optionalAccess', _96 => _96.motif]), () => ( -1))], 'optionalAccess', _97 => _97.intervals, 'access', _98 => _98.length]), () => ( 0))) + 1;
|
|
6774
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, graph.nodes.length * phrases.length, "plan motif selection", asked.budget);
|
|
6474
6775
|
const candidates = [];
|
|
6475
6776
|
graph.nodes.forEach((node, index) => {
|
|
6476
6777
|
const phrase = phraseHolding(phrases, node.startBeat, node.endBeat);
|
|
@@ -6491,8 +6792,8 @@ function deriveCompositionPlan(reference, opts) {
|
|
|
6491
6792
|
const { from, relation } = selectedDerivation(graph, parentEdge, selectedAt, candidate.node);
|
|
6492
6793
|
const keepRelation = draw.prob(preserve.motifRelations, "motifRelations", index);
|
|
6493
6794
|
const keepRhythm = from === null && draw.prob(preserve.rhythm, "rhythm", index);
|
|
6494
|
-
const cell = profile.melody.motifs[_nullishCoalesce(_optionalChain([graph, 'access',
|
|
6495
|
-
_optionalChain([phrases, 'access',
|
|
6795
|
+
const cell = profile.melody.motifs[_nullishCoalesce(_optionalChain([graph, 'access', _99 => _99.nodes, 'access', _100 => _100[candidate.node], 'optionalAccess', _101 => _101.motif]), () => ( -1))];
|
|
6796
|
+
_optionalChain([phrases, 'access', _102 => _102[candidate.phrase], 'optionalAccess', _103 => _103.motifs, 'access', _104 => _104.push, 'call', _105 => _105(index)]);
|
|
6496
6797
|
return {
|
|
6497
6798
|
phrase: candidate.phrase,
|
|
6498
6799
|
startBeat: candidate.startBeat,
|
|
@@ -6529,7 +6830,7 @@ function interiorBoundaries(plan) {
|
|
|
6529
6830
|
const beats = /* @__PURE__ */ new Set();
|
|
6530
6831
|
for (const phrase of plan.phrases) {
|
|
6531
6832
|
for (const beat of [phrase.startBeat, phrase.endBeat]) {
|
|
6532
|
-
if (beat > plan.span.startBeat +
|
|
6833
|
+
if (beat > plan.span.startBeat + _chunkS3QELJUEcjs.BEAT_EPS && beat < plan.span.endBeat - _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6533
6834
|
beats.add(beat);
|
|
6534
6835
|
}
|
|
6535
6836
|
}
|
|
@@ -6540,12 +6841,12 @@ function restsOf(melody, plan) {
|
|
|
6540
6841
|
const rests = [];
|
|
6541
6842
|
let reach = plan.span.startBeat;
|
|
6542
6843
|
for (const note2 of [...melody].sort((a, b) => a.startBeat - b.startBeat)) {
|
|
6543
|
-
if (note2.startBeat > reach +
|
|
6844
|
+
if (note2.startBeat > reach + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6544
6845
|
rests.push({ startBeat: reach, endBeat: note2.startBeat });
|
|
6545
6846
|
}
|
|
6546
6847
|
reach = Math.max(reach, note2.startBeat + note2.durationBeat);
|
|
6547
6848
|
}
|
|
6548
|
-
if (plan.span.endBeat > reach +
|
|
6849
|
+
if (plan.span.endBeat > reach + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6549
6850
|
rests.push({ startBeat: reach, endBeat: plan.span.endBeat });
|
|
6550
6851
|
}
|
|
6551
6852
|
return rests;
|
|
@@ -6554,12 +6855,12 @@ function phraseBoundaryViolations(melody, plan) {
|
|
|
6554
6855
|
const rests = restsOf(melody, plan);
|
|
6555
6856
|
const violations = [];
|
|
6556
6857
|
for (const beat of interiorBoundaries(plan)) {
|
|
6557
|
-
const pulse2 =
|
|
6858
|
+
const pulse2 = _chunkS3QELJUEcjs.pulseBeats.call(void 0, _chunkS3QELJUEcjs.meterAt.call(void 0, beat, plan.meters));
|
|
6558
6859
|
const held = melody.some(
|
|
6559
|
-
(note2) => note2.durationBeat >= HELD_NOTE_BEATS -
|
|
6860
|
+
(note2) => note2.durationBeat >= HELD_NOTE_BEATS - _chunkS3QELJUEcjs.BEAT_EPS && Math.abs(note2.startBeat + note2.durationBeat - beat) <= pulse2 + _chunkS3QELJUEcjs.BEAT_EPS
|
|
6560
6861
|
);
|
|
6561
6862
|
const rested = rests.some(
|
|
6562
|
-
(rest) => rest.endBeat - rest.startBeat >= pulse2 -
|
|
6863
|
+
(rest) => rest.endBeat - rest.startBeat >= pulse2 - _chunkS3QELJUEcjs.BEAT_EPS && rest.startBeat <= beat + pulse2 + _chunkS3QELJUEcjs.BEAT_EPS && rest.endBeat >= beat - pulse2 - _chunkS3QELJUEcjs.BEAT_EPS
|
|
6563
6864
|
);
|
|
6564
6865
|
if (!held && !rested) {
|
|
6565
6866
|
violations.push({
|
|
@@ -6576,7 +6877,7 @@ function phraseBoundaryViolations(melody, plan) {
|
|
|
6576
6877
|
}
|
|
6577
6878
|
function spanViolation(melody, plan) {
|
|
6578
6879
|
const end = melody.reduce((max, note2) => Math.max(max, note2.startBeat + note2.durationBeat), 0);
|
|
6579
|
-
if (end <= plan.span.endBeat +
|
|
6880
|
+
if (end <= plan.span.endBeat + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
6580
6881
|
return [];
|
|
6581
6882
|
}
|
|
6582
6883
|
return [
|
|
@@ -6593,7 +6894,7 @@ function spanViolation(melody, plan) {
|
|
|
6593
6894
|
function phraseLines(melody, plan) {
|
|
6594
6895
|
return plan.phrases.map(
|
|
6595
6896
|
(phrase) => melody.flatMap(
|
|
6596
|
-
(note2, index) => note2.startBeat >= phrase.startBeat -
|
|
6897
|
+
(note2, index) => note2.startBeat >= phrase.startBeat - _chunkS3QELJUEcjs.BEAT_EPS && note2.startBeat < phrase.endBeat - _chunkS3QELJUEcjs.BEAT_EPS ? [index] : []
|
|
6597
6898
|
)
|
|
6598
6899
|
);
|
|
6599
6900
|
}
|
|
@@ -6603,10 +6904,10 @@ function cadenceViolations(melody, plan, timeline, lines) {
|
|
|
6603
6904
|
if (phrase.cadence === null) {
|
|
6604
6905
|
return;
|
|
6605
6906
|
}
|
|
6606
|
-
const last = _optionalChain([lines, 'access',
|
|
6907
|
+
const last = _optionalChain([lines, 'access', _106 => _106[index], 'optionalAccess', _107 => _107.at, 'call', _108 => _108(-1)]);
|
|
6607
6908
|
const note2 = last === void 0 ? void 0 : melody[last];
|
|
6608
6909
|
const allowed = note2 === void 0 ? [] : cadencePitchClasses(plan, timeline, phrase.cadence, note2.startBeat);
|
|
6609
|
-
if (note2 !== void 0 && (allowed === null || allowed.includes(
|
|
6910
|
+
if (note2 !== void 0 && (allowed === null || allowed.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, note2.pitch)))) {
|
|
6610
6911
|
return;
|
|
6611
6912
|
}
|
|
6612
6913
|
violations.push({
|
|
@@ -6631,9 +6932,9 @@ function harmonyViolations(melody, plan, timeline, lines) {
|
|
|
6631
6932
|
}
|
|
6632
6933
|
const note2 = melody[line[at2]];
|
|
6633
6934
|
const derived = plan.motifs.some(
|
|
6634
|
-
(motif) => motif.from !== null && note2.startBeat >= motif.startBeat -
|
|
6935
|
+
(motif) => motif.from !== null && note2.startBeat >= motif.startBeat - _chunkS3QELJUEcjs.BEAT_EPS && note2.startBeat < motif.endBeat - _chunkS3QELJUEcjs.BEAT_EPS
|
|
6635
6936
|
);
|
|
6636
|
-
const strong = positionClass(note2.startBeat, plan.meters) === "strong";
|
|
6937
|
+
const strong = positionClass(note2.startBeat, plan.meters) === "strong" && timeline.at(note2.startBeat) !== null;
|
|
6637
6938
|
violations.push({
|
|
6638
6939
|
kind: "harmony",
|
|
6639
6940
|
severity: derived ? "warning" : "error",
|
|
@@ -6648,10 +6949,19 @@ function harmonyViolations(melody, plan, timeline, lines) {
|
|
|
6648
6949
|
}
|
|
6649
6950
|
function notesInRange(melody, startBeat, endBeat) {
|
|
6650
6951
|
return melody.filter(
|
|
6651
|
-
(note2) => note2.startBeat >= startBeat -
|
|
6952
|
+
(note2) => note2.startBeat >= startBeat - _chunkS3QELJUEcjs.BEAT_EPS && note2.startBeat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS
|
|
6652
6953
|
);
|
|
6653
6954
|
}
|
|
6654
|
-
function
|
|
6955
|
+
function keptEnd(statement, melody, plan) {
|
|
6956
|
+
const phrase = phraseAt(plan, statement.startBeat);
|
|
6957
|
+
if (phrase === void 0) {
|
|
6958
|
+
return statement.endBeat;
|
|
6959
|
+
}
|
|
6960
|
+
const downbeat = finalDownbeat(phrase, plan.meters);
|
|
6961
|
+
const held = notesInRange(melody, downbeat, phrase.endBeat).length === 1;
|
|
6962
|
+
return held ? Math.min(statement.endBeat, downbeat) : statement.endBeat;
|
|
6963
|
+
}
|
|
6964
|
+
function replayLevel(source, derived, statement, sourceEnd, derivedEnd, sourceCut, plan, key, closing) {
|
|
6655
6965
|
const relation = statement.relation;
|
|
6656
6966
|
const planned = relation.kind === "tonalTransposition" ? _nullishCoalesce(relation.degrees, () => ( 0)) : relation.semitones;
|
|
6657
6967
|
const { low, high } = plan.phrases[statement.phrase].register;
|
|
@@ -6668,24 +6978,25 @@ function replayLevel(source, derived, statement, sourceEnd, plan, key, closing)
|
|
|
6668
6978
|
const replays = relationLevels(relation.kind).map((level) => {
|
|
6669
6979
|
const notes = clipStatement(
|
|
6670
6980
|
replayAt(cell, relation, level, statement.startBeat, key),
|
|
6671
|
-
|
|
6981
|
+
derivedEnd
|
|
6672
6982
|
);
|
|
6673
6983
|
return { level, notes, outside: notes.filter((note2) => outside(note2.pitch)).length };
|
|
6674
6984
|
});
|
|
6675
6985
|
const fewestOutside = Math.min(...replays.map((replay) => replay.outside));
|
|
6676
6986
|
let best = null;
|
|
6677
6987
|
for (const { level, notes: expected, outside: away } of replays) {
|
|
6678
|
-
|
|
6988
|
+
const compared = sourceCut ? derived.slice(0, expected.length) : derived;
|
|
6989
|
+
if (expected.length !== compared.length) {
|
|
6679
6990
|
continue;
|
|
6680
6991
|
}
|
|
6681
6992
|
let forced = 0;
|
|
6682
6993
|
let holds = true;
|
|
6683
6994
|
for (let i = 0; holds && i < expected.length; i += 1) {
|
|
6684
6995
|
const want = expected[i];
|
|
6685
|
-
const got =
|
|
6996
|
+
const got = compared[i];
|
|
6686
6997
|
if (i > 0) {
|
|
6687
|
-
const gap = got.startBeat -
|
|
6688
|
-
holds = Math.abs(gap - (want.startBeat - expected[i - 1].startBeat)) <=
|
|
6998
|
+
const gap = got.startBeat - compared[i - 1].startBeat;
|
|
6999
|
+
holds = Math.abs(gap - (want.startBeat - expected[i - 1].startBeat)) <= _chunkS3QELJUEcjs.BEAT_EPS;
|
|
6689
7000
|
}
|
|
6690
7001
|
if (!holds || got.pitch === want.pitch) {
|
|
6691
7002
|
continue;
|
|
@@ -6715,6 +7026,11 @@ function motifDerivationViolations(melody, plan, closing) {
|
|
|
6715
7026
|
const derivedNotes = notesInRange(melody, statement.startBeat, statement.endBeat);
|
|
6716
7027
|
const relation = statement.relation;
|
|
6717
7028
|
const rationale = `the statement at beat ${statement.startBeat} does not derive from its source the way the plan names`;
|
|
7029
|
+
const sourceKept = keptEnd(source, melody, plan);
|
|
7030
|
+
const derivedKept = keptEnd(statement, melody, plan);
|
|
7031
|
+
if (sourceKept <= source.startBeat + _chunkS3QELJUEcjs.BEAT_EPS || derivedKept <= statement.startBeat + _chunkS3QELJUEcjs.BEAT_EPS) {
|
|
7032
|
+
continue;
|
|
7033
|
+
}
|
|
6718
7034
|
if (sourceNotes.length === 0 || derivedNotes.length === 0) {
|
|
6719
7035
|
errors.push({
|
|
6720
7036
|
kind: "motifDerivation",
|
|
@@ -6726,27 +7042,43 @@ function motifDerivationViolations(melody, plan, closing) {
|
|
|
6726
7042
|
});
|
|
6727
7043
|
continue;
|
|
6728
7044
|
}
|
|
7045
|
+
const sourceCut = sourceKept < source.endBeat - _chunkS3QELJUEcjs.BEAT_EPS;
|
|
7046
|
+
const derivedCut = derivedKept < statement.endBeat - _chunkS3QELJUEcjs.BEAT_EPS;
|
|
6729
7047
|
if (relation === null) {
|
|
6730
|
-
const
|
|
6731
|
-
|
|
7048
|
+
const sourceEnd = derivedCut ? Math.min(sourceKept, source.startBeat + derivedKept - statement.startBeat) : sourceKept;
|
|
7049
|
+
const derivedEnd = sourceCut ? Math.min(derivedKept, statement.startBeat + sourceKept - source.startBeat) : derivedKept;
|
|
7050
|
+
const sourceLine = notesInRange(melody, source.startBeat, sourceEnd);
|
|
7051
|
+
const derivedLine = notesInRange(melody, statement.startBeat, derivedEnd);
|
|
7052
|
+
if (sourceLine.length === 0 || derivedLine.length === 0) {
|
|
7053
|
+
continue;
|
|
7054
|
+
}
|
|
7055
|
+
const similarity = _chunkLQZQDBCDcjs.melodicSimilarity.call(void 0, sourceLine, derivedLine);
|
|
7056
|
+
if (similarity < _chunkLQZQDBCDcjs.DEFAULT_VARIATION_THRESHOLD) {
|
|
6732
7057
|
errors.push({
|
|
6733
7058
|
kind: "motifDerivation",
|
|
6734
7059
|
severity: "error",
|
|
6735
7060
|
atBeat: statement.startBeat,
|
|
6736
|
-
expected: `a variation (melodicSimilarity >= ${
|
|
7061
|
+
expected: `a variation (melodicSimilarity >= ${_chunkLQZQDBCDcjs.DEFAULT_VARIATION_THRESHOLD})`,
|
|
6737
7062
|
actual: `melodicSimilarity ${similarity.toFixed(3)}`,
|
|
6738
7063
|
rationale
|
|
6739
7064
|
});
|
|
6740
7065
|
}
|
|
6741
7066
|
continue;
|
|
6742
7067
|
}
|
|
7068
|
+
const kept = notesInRange(melody, source.startBeat, sourceKept);
|
|
7069
|
+
const backward = relation.kind === "retrograde" || relation.kind === "retrogradeInversion";
|
|
7070
|
+
if (kept.length === 0 || sourceCut && backward) {
|
|
7071
|
+
continue;
|
|
7072
|
+
}
|
|
6743
7073
|
const replay = replayLevel(
|
|
6744
|
-
|
|
6745
|
-
|
|
7074
|
+
kept,
|
|
7075
|
+
notesInRange(melody, statement.startBeat, derivedKept),
|
|
6746
7076
|
statement,
|
|
6747
|
-
|
|
7077
|
+
sourceKept,
|
|
7078
|
+
derivedKept,
|
|
7079
|
+
sourceCut,
|
|
6748
7080
|
plan,
|
|
6749
|
-
|
|
7081
|
+
_chunkYDGMWH43cjs.scaleOf.call(void 0, keyAt(statement.startBeat)),
|
|
6750
7082
|
closing
|
|
6751
7083
|
);
|
|
6752
7084
|
const planned = relation.kind === "tonalTransposition" ? _nullishCoalesce(relation.degrees, () => ( 0)) : relation.semitones;
|
|
@@ -6774,7 +7106,7 @@ function motifDerivationViolations(melody, plan, closing) {
|
|
|
6774
7106
|
}
|
|
6775
7107
|
function phraseAt(plan, beat) {
|
|
6776
7108
|
return plan.phrases.find(
|
|
6777
|
-
(phrase) => beat >= phrase.startBeat -
|
|
7109
|
+
(phrase) => beat >= phrase.startBeat - _chunkS3QELJUEcjs.BEAT_EPS && beat < phrase.endBeat - _chunkS3QELJUEcjs.BEAT_EPS
|
|
6778
7110
|
);
|
|
6779
7111
|
}
|
|
6780
7112
|
function registerViolations(melody, plan) {
|
|
@@ -6876,7 +7208,7 @@ function planDensity(plan) {
|
|
|
6876
7208
|
let weighted = 0;
|
|
6877
7209
|
let bars = 0;
|
|
6878
7210
|
for (const phrase of plan.phrases) {
|
|
6879
|
-
const span =
|
|
7211
|
+
const span = _chunkLQZQDBCDcjs.barSpanOf.call(void 0, phrase.startBeat, phrase.endBeat, plan.meters);
|
|
6880
7212
|
weighted += phrase.onsetDensity * span;
|
|
6881
7213
|
bars += span;
|
|
6882
7214
|
}
|
|
@@ -6884,9 +7216,9 @@ function planDensity(plan) {
|
|
|
6884
7216
|
}
|
|
6885
7217
|
function evaluateComposition(melody, plan, opts) {
|
|
6886
7218
|
assertCompositionPlan(plan, "evaluated plan");
|
|
6887
|
-
const { budget } =
|
|
7219
|
+
const { budget } = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "evaluate options");
|
|
6888
7220
|
const notes = [
|
|
6889
|
-
...
|
|
7221
|
+
..._chunkS3QELJUEcjs.assertNoteEvents.call(void 0, melody, "evaluated melody", { budget, allowNonPositiveDuration: true })
|
|
6890
7222
|
].sort((a, b) => a.startBeat - b.startBeat);
|
|
6891
7223
|
const timeline = planChordTimeline(plan);
|
|
6892
7224
|
const lines = phraseLines(notes, plan);
|
|
@@ -6896,7 +7228,7 @@ function evaluateComposition(melody, plan, opts) {
|
|
|
6896
7228
|
const derivations = motifDerivationViolations(notes, plan, closing);
|
|
6897
7229
|
const lineMean = lineMeanOf(notes);
|
|
6898
7230
|
const readings = plan.phrases.map(
|
|
6899
|
-
(phrase) =>
|
|
7231
|
+
(phrase) => _chunkLQZQDBCDcjs.phraseMelody.call(void 0, notes, phrase.startBeat, phrase.endBeat, _nullishCoalesce(lineMean, () => ( 0)), plan.meters, budget)
|
|
6900
7232
|
);
|
|
6901
7233
|
const violations = [
|
|
6902
7234
|
...spanViolation(notes, plan),
|
|
@@ -6908,19 +7240,19 @@ function evaluateComposition(melody, plan, opts) {
|
|
|
6908
7240
|
...derivations.warnings,
|
|
6909
7241
|
...peakPositionWarnings(plan, readings)
|
|
6910
7242
|
];
|
|
6911
|
-
const rhythm =
|
|
7243
|
+
const rhythm = _chunkLQZQDBCDcjs.analyzeRhythm.call(void 0, notes, {
|
|
6912
7244
|
meters: plan.meters,
|
|
6913
7245
|
totalBeats: plan.span.endBeat,
|
|
6914
7246
|
budget
|
|
6915
7247
|
});
|
|
6916
7248
|
const target = planRhythmReading(plan);
|
|
6917
7249
|
const fit = {
|
|
6918
|
-
contour:
|
|
6919
|
-
register:
|
|
6920
|
-
onset:
|
|
6921
|
-
duration:
|
|
6922
|
-
syncopation:
|
|
6923
|
-
density:
|
|
7250
|
+
contour: _chunkLQZQDBCDcjs.contourSimilarity.call(void 0, plan.phrases.map(planContourPhrase), readings),
|
|
7251
|
+
register: _chunkLQZQDBCDcjs.registerSimilarity.call(void 0, planRegisterPlan(plan), { phrases: readings, mean: lineMean }),
|
|
7252
|
+
onset: _chunkLQZQDBCDcjs.onsetSimilarity.call(void 0, target, rhythm),
|
|
7253
|
+
duration: _chunkLQZQDBCDcjs.durationSimilarity.call(void 0, target, rhythm),
|
|
7254
|
+
syncopation: _chunkLQZQDBCDcjs.syncopationSimilarity.call(void 0, target, rhythm),
|
|
7255
|
+
density: _chunkLQZQDBCDcjs.densitySimilarity.call(void 0, planDensity(plan), rhythm)
|
|
6924
7256
|
};
|
|
6925
7257
|
return { violations, fit };
|
|
6926
7258
|
}
|
|
@@ -7111,23 +7443,23 @@ function progressions() {
|
|
|
7111
7443
|
return PRESETS.map((p) => ({ ...p, degrees: [...p.degrees], styles: [...p.styles] }));
|
|
7112
7444
|
}
|
|
7113
7445
|
function progressionsByStyle(style) {
|
|
7114
|
-
const named =
|
|
7446
|
+
const named = _chunkS3QELJUEcjs.assertOneOf.call(void 0, style, PROG_STYLES, "style");
|
|
7115
7447
|
return progressions().filter((p) => p.styles.includes(named));
|
|
7116
7448
|
}
|
|
7117
7449
|
function degreeToRootPc(degree, key) {
|
|
7118
7450
|
if (degree >= 1 && degree <= 7) {
|
|
7119
|
-
const tones =
|
|
7451
|
+
const tones = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, _chunkYDGMWH43cjs.heptatonicFrameOf.call(void 0, key));
|
|
7120
7452
|
return _nullishCoalesce(tones[degree - 1], () => ( key.rootPc % 12));
|
|
7121
7453
|
}
|
|
7122
7454
|
const offset = _nullishCoalesce(BORROWED_OFFSET[degree], () => ( 0));
|
|
7123
7455
|
return ((key.rootPc % 12 + offset) % 12 + 12) % 12;
|
|
7124
7456
|
}
|
|
7125
|
-
function autoQuality(degree, key, harmonicDominant) {
|
|
7457
|
+
function autoQuality(degree, key, tonic, harmonicDominant) {
|
|
7126
7458
|
if (degree >= 1 && degree <= 7) {
|
|
7127
|
-
if (harmonicDominant &&
|
|
7459
|
+
if (harmonicDominant && _chunkYDGMWH43cjs.cadencesThroughRaisedSeventh.call(void 0, key) && degree === 5) {
|
|
7128
7460
|
return "maj";
|
|
7129
7461
|
}
|
|
7130
|
-
return
|
|
7462
|
+
return _chunkYDGMWH43cjs.diatonicTriad.call(void 0, degree, { ..._chunkYDGMWH43cjs.heptatonicFrameOf.call(void 0, key), tonic }).quality;
|
|
7131
7463
|
}
|
|
7132
7464
|
if (degree === 14) {
|
|
7133
7465
|
return "dim";
|
|
@@ -7137,11 +7469,11 @@ function autoQuality(degree, key, harmonicDominant) {
|
|
|
7137
7469
|
}
|
|
7138
7470
|
return "maj";
|
|
7139
7471
|
}
|
|
7140
|
-
function resolveCycle(degrees, key, ext, harmonicDominant) {
|
|
7472
|
+
function resolveCycle(degrees, key, tonic, ext, harmonicDominant) {
|
|
7141
7473
|
const steps = degrees.map((degree) => {
|
|
7142
7474
|
const step = {
|
|
7143
7475
|
rootPc: degreeToRootPc(degree, key),
|
|
7144
|
-
quality: ext !== void 0 && ext !== "auto" ? ext : autoQuality(degree, key, harmonicDominant)
|
|
7476
|
+
quality: ext !== void 0 && ext !== "auto" ? ext : autoQuality(degree, key, tonic, harmonicDominant)
|
|
7145
7477
|
};
|
|
7146
7478
|
if (degree >= 1 && degree <= 7) {
|
|
7147
7479
|
step.degree = degree;
|
|
@@ -7156,72 +7488,82 @@ function pickProgressionPreset(style, ctx = 0) {
|
|
|
7156
7488
|
function presetFor(style, ctx) {
|
|
7157
7489
|
const pool = PRESETS.filter((preset) => preset.styles.includes(style));
|
|
7158
7490
|
if (pool.length === 0) {
|
|
7159
|
-
throw new (0,
|
|
7491
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`Unknown progression style: ${style}`);
|
|
7160
7492
|
}
|
|
7161
7493
|
const index = ctx.part("progression").range(0, pool.length - 1, "preset");
|
|
7162
7494
|
return _nullishCoalesce(pool[index], () => ( PRESETS[0]));
|
|
7163
7495
|
}
|
|
7164
7496
|
function tonicizableRootPcs(key) {
|
|
7165
|
-
return new Set(
|
|
7497
|
+
return new Set(_chunkYDGMWH43cjs.tonicizableDegrees.call(void 0, key).map((degree) => degree.rootPc));
|
|
7166
7498
|
}
|
|
7167
7499
|
function canBeTonicized(span, tonicizable) {
|
|
7168
7500
|
if (!tonicizable.has(span.rootPc)) {
|
|
7169
7501
|
return false;
|
|
7170
7502
|
}
|
|
7171
|
-
return
|
|
7503
|
+
return _chunkYDGMWH43cjs.fifthPcOf.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, span.rootPc, span.quality)) === (span.rootPc + 7) % 12;
|
|
7172
7504
|
}
|
|
7173
7505
|
function generateProgression(opts) {
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
const key =
|
|
7506
|
+
_chunkS3QELJUEcjs.assertRecord.call(void 0, opts, "progression options");
|
|
7507
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, opts.bars, "progression bars");
|
|
7508
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, opts.bars, "progression chords");
|
|
7509
|
+
const { scale: key, tonic } = _chunkYDGMWH43cjs.resolveKey.call(void 0, opts.key);
|
|
7178
7510
|
const ctx = resolveContext(opts.ctx);
|
|
7179
7511
|
let preset;
|
|
7180
7512
|
if (opts.preset !== void 0) {
|
|
7181
|
-
|
|
7182
|
-
|
|
7513
|
+
const custom = _chunkS3QELJUEcjs.assertRecord.call(void 0,
|
|
7514
|
+
opts.preset,
|
|
7515
|
+
"progression preset"
|
|
7516
|
+
);
|
|
7517
|
+
const degrees = _chunkS3QELJUEcjs.assertArray.call(void 0, custom.degrees, "progression preset degrees");
|
|
7518
|
+
if (degrees.length === 0) {
|
|
7519
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)("progression preset must name at least one degree");
|
|
7183
7520
|
}
|
|
7184
7521
|
preset = {
|
|
7185
|
-
id: _nullishCoalesce(
|
|
7186
|
-
name: _nullishCoalesce(
|
|
7187
|
-
degrees:
|
|
7188
|
-
|
|
7522
|
+
id: _nullishCoalesce(custom.id, () => ( "custom")),
|
|
7523
|
+
name: _nullishCoalesce(custom.name, () => ( "Custom")),
|
|
7524
|
+
degrees: degrees.map((degree, index) => {
|
|
7525
|
+
_chunkS3QELJUEcjs.assertDegree.call(void 0, degree, `progression preset degrees[${index}]`);
|
|
7189
7526
|
const supported = degree >= 1 && degree <= 7 || Object.values(BORROWED_DEGREES).includes(degree);
|
|
7190
7527
|
if (!supported) {
|
|
7191
|
-
throw new (0,
|
|
7528
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
|
|
7192
7529
|
`progression preset degrees[${index}] is not a supported progression degree; received ${degree}`
|
|
7193
7530
|
);
|
|
7194
7531
|
}
|
|
7195
7532
|
return degree;
|
|
7196
7533
|
}),
|
|
7197
|
-
functional:
|
|
7198
|
-
|
|
7534
|
+
functional: _chunkS3QELJUEcjs.assertOneOf.call(void 0,
|
|
7535
|
+
_nullishCoalesce(custom.functional, () => ( "loop")),
|
|
7536
|
+
["loop", "tensionBuild", "cadenceStrong", "stable"],
|
|
7537
|
+
"progression preset functional"
|
|
7538
|
+
),
|
|
7539
|
+
styles: _nullishCoalesce(custom.styles, () => ( [opts.style]))
|
|
7199
7540
|
};
|
|
7200
7541
|
}
|
|
7201
7542
|
if (preset === void 0 && opts.presetId !== void 0) {
|
|
7202
7543
|
preset = PRESETS.find((p) => p.id === opts.presetId);
|
|
7203
7544
|
if (preset === void 0) {
|
|
7204
|
-
throw new (0,
|
|
7545
|
+
throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`Unknown progression preset: ${opts.presetId}`);
|
|
7205
7546
|
}
|
|
7206
7547
|
}
|
|
7207
7548
|
preset ??= presetFor(opts.style, ctx);
|
|
7208
|
-
const ext = opts.ext === void 0 ? "auto" :
|
|
7549
|
+
const ext = opts.ext === void 0 ? "auto" : _chunkS3QELJUEcjs.assertOneOf.call(void 0, opts.ext, ["auto", ..._chunkYDGMWH43cjs.chordQualities.call(void 0, )], "progression extension");
|
|
7209
7550
|
const cycle = resolveCycle(
|
|
7210
|
-
_nullishCoalesce(_optionalChain([preset, 'optionalAccess',
|
|
7551
|
+
_nullishCoalesce(_optionalChain([preset, 'optionalAccess', _109 => _109.degrees]), () => ( [0])),
|
|
7211
7552
|
key,
|
|
7553
|
+
tonic,
|
|
7212
7554
|
ext,
|
|
7213
|
-
_optionalChain([preset, 'optionalAccess',
|
|
7555
|
+
_optionalChain([preset, 'optionalAccess', _110 => _110.functional]) === "cadenceStrong"
|
|
7214
7556
|
);
|
|
7215
|
-
const barBeats =
|
|
7557
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_TS6)));
|
|
7216
7558
|
const chords = [];
|
|
7217
7559
|
for (let bar2 = 0; bar2 < opts.bars; bar2 += 1) {
|
|
7218
7560
|
const step = cycle[bar2 % cycle.length];
|
|
7219
7561
|
const chord = {
|
|
7220
|
-
rootPc: _nullishCoalesce(_optionalChain([step, 'optionalAccess',
|
|
7221
|
-
quality: _nullishCoalesce(_optionalChain([step, 'optionalAccess',
|
|
7562
|
+
rootPc: _nullishCoalesce(_optionalChain([step, 'optionalAccess', _111 => _111.rootPc]), () => ( 0)),
|
|
7563
|
+
quality: _nullishCoalesce(_optionalChain([step, 'optionalAccess', _112 => _112.quality]), () => ( "maj")),
|
|
7222
7564
|
startBeat: bar2 * barBeats
|
|
7223
7565
|
};
|
|
7224
|
-
if (_optionalChain([step, 'optionalAccess',
|
|
7566
|
+
if (_optionalChain([step, 'optionalAccess', _113 => _113.degree]) !== void 0) {
|
|
7225
7567
|
chord.degree = step.degree;
|
|
7226
7568
|
}
|
|
7227
7569
|
chords.push(chord);
|
|
@@ -7241,10 +7583,11 @@ function generateProgression(opts) {
|
|
|
7241
7583
|
const domRoot = (next.rootPc + 7) % 12;
|
|
7242
7584
|
const targetsTonic = (next.rootPc - tonicPc + 12) % 12 === 0;
|
|
7243
7585
|
const isLastTonicStatement = cur.rootPc === tonicPc && tonicStatements <= 1;
|
|
7244
|
-
const alreadySecondary = cur.rootPc === domRoot && cur.quality
|
|
7245
|
-
const
|
|
7586
|
+
const alreadySecondary = cur.rootPc === domRoot && _chunkYDGMWH43cjs.soundsDominantSeventh.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, cur.rootPc, cur.quality));
|
|
7587
|
+
const isNativeDominant = _chunkYDGMWH43cjs.isNativeDominantSeventh.call(void 0, domRoot, key);
|
|
7588
|
+
const isResolutionTarget = _optionalChain([chords, 'access', _114 => _114[i - 1], 'optionalAccess', _115 => _115.secondaryDominant]) === true;
|
|
7246
7589
|
const takesNoDominant = !canBeTonicized(next, tonicizable);
|
|
7247
|
-
if (targetsTonic || isLastTonicStatement || alreadySecondary || isResolutionTarget || takesNoDominant) {
|
|
7590
|
+
if (targetsTonic || isLastTonicStatement || alreadySecondary || isResolutionTarget || takesNoDominant || isNativeDominant) {
|
|
7248
7591
|
continue;
|
|
7249
7592
|
}
|
|
7250
7593
|
if (draw.prob(harmonic, "reharmonize", i)) {
|
|
@@ -7269,7 +7612,7 @@ function commonToneCount(a, b) {
|
|
|
7269
7612
|
return a.filter((pc) => set.has(pc)).length;
|
|
7270
7613
|
}
|
|
7271
7614
|
function triadQualityOf(chord) {
|
|
7272
|
-
const semis = new Set(chord.intervals.map((interval) =>
|
|
7615
|
+
const semis = new Set(chord.intervals.map((interval) => _chunkS3QELJUEcjs.pitchClassOf.call(void 0, interval)));
|
|
7273
7616
|
const hasThird = semis.has(4) ? "maj" : semis.has(3) ? "min" : void 0;
|
|
7274
7617
|
if (hasThird === void 0) {
|
|
7275
7618
|
return chord.quality;
|
|
@@ -7282,16 +7625,16 @@ function triadQualityOf(chord) {
|
|
|
7282
7625
|
}
|
|
7283
7626
|
return hasThird;
|
|
7284
7627
|
}
|
|
7285
|
-
function diatonicTriadsOf(key) {
|
|
7286
|
-
const degrees =
|
|
7628
|
+
function diatonicTriadsOf(key, tonic) {
|
|
7629
|
+
const degrees = _chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, key).length;
|
|
7287
7630
|
const triads = [];
|
|
7288
7631
|
for (let degree = 1; degree <= degrees; degree += 1) {
|
|
7289
|
-
triads.push(
|
|
7632
|
+
triads.push(_chunkYDGMWH43cjs.diatonicTriad.call(void 0, degree, { ...key, tonic }));
|
|
7290
7633
|
}
|
|
7291
7634
|
return triads;
|
|
7292
7635
|
}
|
|
7293
7636
|
function sameChord(a, b) {
|
|
7294
|
-
return
|
|
7637
|
+
return _chunkS3QELJUEcjs.pitchClassOf.call(void 0, a.rootPc) === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, b.rootPc) && a.quality === b.quality;
|
|
7295
7638
|
}
|
|
7296
7639
|
var THIRD_OFFSETS = [3, 4, 8, 9];
|
|
7297
7640
|
var MAX_HINT_ALTER = 2;
|
|
@@ -7299,75 +7642,90 @@ function bareSpelling(note2) {
|
|
|
7299
7642
|
return { letter: note2.letter, alter: note2.alter };
|
|
7300
7643
|
}
|
|
7301
7644
|
function spelledOnRoot(chord, root, tonic, key) {
|
|
7302
|
-
const usable =
|
|
7645
|
+
const usable = _chunkS3QELJUEcjs.noteToPitchClass.call(void 0, root) === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc) && Math.abs(root.alter) <= MAX_HINT_ALTER;
|
|
7303
7646
|
const spelled = {
|
|
7304
7647
|
...chord,
|
|
7305
|
-
rootSpelling: bareSpelling(usable ? root :
|
|
7648
|
+
rootSpelling: bareSpelling(usable ? root : _chunkYDGMWH43cjs.spellPitchClass.call(void 0, chord.rootPc, tonic, key))
|
|
7306
7649
|
};
|
|
7307
7650
|
if (chord.bassPc !== void 0) {
|
|
7308
|
-
spelled.bassSpelling = bareSpelling(
|
|
7651
|
+
spelled.bassSpelling = bareSpelling(_chunkYDGMWH43cjs.spellPitchClass.call(void 0, chord.bassPc, tonic, key));
|
|
7309
7652
|
}
|
|
7310
7653
|
return spelled;
|
|
7311
7654
|
}
|
|
7312
7655
|
function spelledInKey(chord, tonic, key) {
|
|
7313
|
-
return spelledOnRoot(chord,
|
|
7656
|
+
return spelledOnRoot(chord, _chunkYDGMWH43cjs.spellPitchClass.call(void 0, chord.rootPc, tonic, key), tonic, key);
|
|
7314
7657
|
}
|
|
7315
7658
|
function tritoneSubstituteRoot(dominant, tonic, key) {
|
|
7316
|
-
const substituteRootPc =
|
|
7317
|
-
if (
|
|
7318
|
-
return
|
|
7319
|
-
}
|
|
7320
|
-
const resolution =
|
|
7321
|
-
return
|
|
7659
|
+
const substituteRootPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, dominant.rootPc + 6);
|
|
7660
|
+
if (_chunkYDGMWH43cjs.isScaleTone.call(void 0, substituteRootPc, key)) {
|
|
7661
|
+
return _chunkYDGMWH43cjs.spellPitchClass.call(void 0, substituteRootPc, tonic, key);
|
|
7662
|
+
}
|
|
7663
|
+
const resolution = _chunkYDGMWH43cjs.spellPitchClass.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, dominant.rootPc + 5), tonic, key);
|
|
7664
|
+
return _chunkS3QELJUEcjs.transposeNote.call(void 0, resolution, 1);
|
|
7665
|
+
}
|
|
7666
|
+
var MEDIANT_THIRDS = {
|
|
7667
|
+
3: "m3",
|
|
7668
|
+
4: "M3",
|
|
7669
|
+
8: "-M3",
|
|
7670
|
+
9: "-m3"
|
|
7671
|
+
};
|
|
7672
|
+
function mediantRoot(source, offset, tonic, key) {
|
|
7673
|
+
const hint = source.rootSpelling;
|
|
7674
|
+
const root = hint !== void 0 && _chunkS3QELJUEcjs.noteToPitchClass.call(void 0, hint) === _chunkS3QELJUEcjs.pitchClassOf.call(void 0, source.rootPc) ? hint : _chunkYDGMWH43cjs.spellPitchClass.call(void 0, source.rootPc, tonic, key);
|
|
7675
|
+
return _chunkS3QELJUEcjs.transposeByInterval.call(void 0, bareSpelling(root), MEDIANT_THIRDS[offset]);
|
|
7322
7676
|
}
|
|
7323
7677
|
function substituteChord(chord, key, opts) {
|
|
7324
|
-
|
|
7325
|
-
const source =
|
|
7326
|
-
const
|
|
7327
|
-
const
|
|
7678
|
+
_chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
7679
|
+
const source = _chunkYDGMWH43cjs.toChordData.call(void 0, chord);
|
|
7680
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, key);
|
|
7681
|
+
const { scale, tonic } = resolved;
|
|
7682
|
+
const originalTriad = _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, source.rootPc, triadQualityOf(source)));
|
|
7328
7683
|
const candidates = [];
|
|
7329
|
-
if (
|
|
7330
|
-
const substitute =
|
|
7684
|
+
if (_chunkYDGMWH43cjs.soundsDominantSeventh.call(void 0, source)) {
|
|
7685
|
+
const substitute = _chunkYDGMWH43cjs.makeChord.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, source.rootPc + 6), "dom7");
|
|
7331
7686
|
candidates.push({
|
|
7332
7687
|
chord: spelledOnRoot(substitute, tritoneSubstituteRoot(source, tonic, scale), tonic, scale),
|
|
7333
7688
|
type: "tritone"
|
|
7334
7689
|
});
|
|
7335
7690
|
}
|
|
7336
|
-
for (const triad of diatonicTriadsOf(scale)) {
|
|
7337
|
-
const offset =
|
|
7338
|
-
if (THIRD_OFFSETS.includes(offset) && commonToneCount(originalTriad,
|
|
7691
|
+
for (const triad of diatonicTriadsOf(scale, tonic)) {
|
|
7692
|
+
const offset = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, triad.rootPc - source.rootPc);
|
|
7693
|
+
if (THIRD_OFFSETS.includes(offset) && commonToneCount(originalTriad, _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, triad)) === 2) {
|
|
7339
7694
|
candidates.push({ chord: spelledInKey(triad, tonic, scale), type: "relative" });
|
|
7340
7695
|
}
|
|
7341
7696
|
}
|
|
7342
|
-
const targetFunction =
|
|
7343
|
-
const parallel =
|
|
7344
|
-
for (const triad of diatonicTriadsOf(parallel)) {
|
|
7345
|
-
if (
|
|
7697
|
+
const targetFunction = _chunkLQZQDBCDcjs.functionOf.call(void 0, source, resolved);
|
|
7698
|
+
const parallel = _chunkLQZQDBCDcjs.parallelKey.call(void 0, scale);
|
|
7699
|
+
for (const triad of diatonicTriadsOf(parallel, tonic)) {
|
|
7700
|
+
if (_chunkLQZQDBCDcjs.functionOf.call(void 0, triad, resolved) === targetFunction && !_chunkLQZQDBCDcjs.isDiatonic.call(void 0, triad, resolved)) {
|
|
7346
7701
|
candidates.push({ chord: spelledInKey(triad, tonic, parallel), type: "borrowed" });
|
|
7347
7702
|
}
|
|
7348
7703
|
}
|
|
7349
7704
|
for (const offset of THIRD_OFFSETS) {
|
|
7350
7705
|
for (const quality of ["maj", "min"]) {
|
|
7351
|
-
const mediant =
|
|
7352
|
-
if (commonToneCount(originalTriad,
|
|
7353
|
-
candidates.push({
|
|
7706
|
+
const mediant = _chunkYDGMWH43cjs.makeChord.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, source.rootPc + offset), quality);
|
|
7707
|
+
if (commonToneCount(originalTriad, _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, mediant)) === 1 && !_chunkLQZQDBCDcjs.isDiatonic.call(void 0, mediant, resolved)) {
|
|
7708
|
+
candidates.push({
|
|
7709
|
+
chord: spelledOnRoot(mediant, mediantRoot(source, offset, tonic, scale), tonic, scale),
|
|
7710
|
+
type: "chromaticMediant"
|
|
7711
|
+
});
|
|
7354
7712
|
}
|
|
7355
7713
|
}
|
|
7356
7714
|
}
|
|
7357
|
-
const melodyPcs = _optionalChain([opts, 'optionalAccess',
|
|
7715
|
+
const melodyPcs = _optionalChain([opts, 'optionalAccess', _116 => _116.melodyPcs, 'optionalAccess', _117 => _117.map, 'call', _118 => _118(_chunkS3QELJUEcjs.pitchClassOf)]);
|
|
7358
7716
|
const seen = /* @__PURE__ */ new Set();
|
|
7359
7717
|
const results = [];
|
|
7360
7718
|
for (const candidate of candidates) {
|
|
7361
7719
|
if (sameChord(candidate.chord, source)) {
|
|
7362
7720
|
continue;
|
|
7363
7721
|
}
|
|
7364
|
-
const dedupeKey = `${
|
|
7722
|
+
const dedupeKey = `${_chunkS3QELJUEcjs.pitchClassOf.call(void 0, candidate.chord.rootPc)}:${candidate.chord.quality}`;
|
|
7365
7723
|
if (seen.has(dedupeKey)) {
|
|
7366
7724
|
continue;
|
|
7367
7725
|
}
|
|
7368
7726
|
seen.add(dedupeKey);
|
|
7369
7727
|
if (melodyPcs !== void 0) {
|
|
7370
|
-
const pcs = new Set(
|
|
7728
|
+
const pcs = new Set(_chunkYDGMWH43cjs.chordPitchClasses.call(void 0, candidate.chord));
|
|
7371
7729
|
if (!melodyPcs.every((pc) => pcs.has(pc))) {
|
|
7372
7730
|
continue;
|
|
7373
7731
|
}
|
|
@@ -7375,76 +7733,78 @@ function substituteChord(chord, key, opts) {
|
|
|
7375
7733
|
results.push({
|
|
7376
7734
|
chord: candidate.chord,
|
|
7377
7735
|
type: candidate.type,
|
|
7378
|
-
roman:
|
|
7379
|
-
function:
|
|
7736
|
+
roman: _chunkLQZQDBCDcjs.chordToRoman.call(void 0, candidate.chord, resolved),
|
|
7737
|
+
function: _chunkLQZQDBCDcjs.functionOf.call(void 0, candidate.chord, resolved)
|
|
7380
7738
|
});
|
|
7381
7739
|
}
|
|
7382
7740
|
return results;
|
|
7383
7741
|
}
|
|
7384
7742
|
function modalInterchangePalette(key) {
|
|
7385
|
-
const
|
|
7743
|
+
const resolved = _chunkYDGMWH43cjs.resolveKey.call(void 0, key);
|
|
7744
|
+
const { scale, tonic } = resolved;
|
|
7386
7745
|
const palette = [];
|
|
7387
7746
|
const seen = /* @__PURE__ */ new Set();
|
|
7388
7747
|
const add = (chord) => {
|
|
7389
|
-
const dedupeKey = `${
|
|
7748
|
+
const dedupeKey = `${_chunkS3QELJUEcjs.pitchClassOf.call(void 0, chord.rootPc)}:${chord.quality}`;
|
|
7390
7749
|
if (seen.has(dedupeKey)) {
|
|
7391
7750
|
return;
|
|
7392
7751
|
}
|
|
7393
7752
|
seen.add(dedupeKey);
|
|
7394
7753
|
palette.push({
|
|
7395
7754
|
chord,
|
|
7396
|
-
roman:
|
|
7397
|
-
source:
|
|
7755
|
+
roman: _chunkLQZQDBCDcjs.chordToRoman.call(void 0, chord, resolved),
|
|
7756
|
+
source: _chunkLQZQDBCDcjs.borrowedSource.call(void 0, chord, resolved)
|
|
7398
7757
|
});
|
|
7399
7758
|
};
|
|
7400
|
-
const parallel =
|
|
7401
|
-
for (const triad of diatonicTriadsOf(parallel)) {
|
|
7402
|
-
if (!
|
|
7759
|
+
const parallel = _chunkLQZQDBCDcjs.parallelKey.call(void 0, scale);
|
|
7760
|
+
for (const triad of diatonicTriadsOf(parallel, tonic)) {
|
|
7761
|
+
if (!_chunkLQZQDBCDcjs.isDiatonic.call(void 0, triad, resolved) && _chunkLQZQDBCDcjs.borrowedSource.call(void 0, triad, resolved) !== null) {
|
|
7403
7762
|
add(spelledInKey(triad, tonic, parallel));
|
|
7404
7763
|
}
|
|
7405
7764
|
}
|
|
7406
|
-
const neapolitan =
|
|
7407
|
-
if (!
|
|
7408
|
-
add(spelledOnRoot(neapolitan,
|
|
7765
|
+
const neapolitan = _chunkYDGMWH43cjs.makeChord.call(void 0, _chunkS3QELJUEcjs.pitchClassOf.call(void 0, scale.rootPc + 1), "maj");
|
|
7766
|
+
if (!_chunkLQZQDBCDcjs.isDiatonic.call(void 0, neapolitan, resolved)) {
|
|
7767
|
+
add(spelledOnRoot(neapolitan, _chunkS3QELJUEcjs.transposeNote.call(void 0, tonic, 1), tonic, scale));
|
|
7409
7768
|
}
|
|
7410
7769
|
return palette;
|
|
7411
7770
|
}
|
|
7412
7771
|
function negativeHarmonyMirror(chord, key) {
|
|
7413
|
-
const source =
|
|
7414
|
-
const { scale, tonic } =
|
|
7415
|
-
const tonicPc =
|
|
7416
|
-
const mirror = (p) =>
|
|
7417
|
-
const pcs =
|
|
7772
|
+
const source = _chunkYDGMWH43cjs.toChordData.call(void 0, chord);
|
|
7773
|
+
const { scale, tonic } = _chunkYDGMWH43cjs.resolveKey.call(void 0, key);
|
|
7774
|
+
const tonicPc = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, scale.rootPc);
|
|
7775
|
+
const mirror = (p) => _chunkS3QELJUEcjs.pitchClassOf.call(void 0, 2 * tonicPc + 7 - p);
|
|
7776
|
+
const pcs = _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, source).map(mirror);
|
|
7418
7777
|
const bassPc = source.bassPc !== void 0 ? mirror(source.bassPc) : void 0;
|
|
7419
7778
|
const pitches = bassPc !== void 0 ? [bassPc, ...pcs.map((pc) => pc + 12)] : pcs;
|
|
7420
|
-
const detected =
|
|
7779
|
+
const detected = _chunkLQZQDBCDcjs.detectChordBest.call(void 0, pitches);
|
|
7421
7780
|
if (detected) {
|
|
7422
7781
|
if (bassPc === void 0 && detected.bassPc !== void 0) {
|
|
7423
|
-
return spelledInKey(
|
|
7782
|
+
return spelledInKey(_chunkYDGMWH43cjs.makeChord.call(void 0, detected.rootPc, detected.quality), tonic, scale);
|
|
7424
7783
|
}
|
|
7425
7784
|
return spelledInKey(detected, tonic, scale);
|
|
7426
7785
|
}
|
|
7427
7786
|
const quality = source.quality;
|
|
7428
|
-
return spelledInKey(
|
|
7787
|
+
return spelledInKey(_chunkYDGMWH43cjs.makeChord.call(void 0, mirror(source.rootPc), quality, bassPc), tonic, scale);
|
|
7429
7788
|
}
|
|
7430
7789
|
|
|
7431
7790
|
// src/generate/rhythm/index.ts
|
|
7432
7791
|
var DEFAULT_RHYTHM_VELOCITY = 96;
|
|
7433
7792
|
function rhythmToNoteEvents(events, pitch, velocity = DEFAULT_RHYTHM_VELOCITY) {
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
return
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7793
|
+
_chunkS3QELJUEcjs.assertMidiPitch.call(void 0, pitch, "pitch");
|
|
7794
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, velocity, "velocity", 0, 127);
|
|
7795
|
+
return _chunkS3QELJUEcjs.assertArray.call(void 0, events, "events").map((given, index) => {
|
|
7796
|
+
const event = _chunkS3QELJUEcjs.assertRecord.call(void 0, given, `events[${index}]`);
|
|
7797
|
+
const bound = Number.MAX_SAFE_INTEGER;
|
|
7798
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, event.position, -bound, bound, `events[${index}].position`);
|
|
7799
|
+
_chunkS3QELJUEcjs.assertRange.call(void 0, event.duration, -bound, bound, `events[${index}].duration`);
|
|
7800
|
+
return { pitch, startBeat: event.position, durationBeat: event.duration, velocity };
|
|
7801
|
+
});
|
|
7442
7802
|
}
|
|
7443
7803
|
var DEFAULT_SUBDIVISION = 2;
|
|
7444
7804
|
var DEFAULT_DENSITY = 0.5;
|
|
7445
7805
|
var DEFAULT_BARS = 1;
|
|
7446
7806
|
function onsetWeightCurve(weight) {
|
|
7447
|
-
|
|
7807
|
+
_chunkS3QELJUEcjs.assertInteger.call(void 0, weight, "weight", 0, 3);
|
|
7448
7808
|
switch (weight) {
|
|
7449
7809
|
case 3:
|
|
7450
7810
|
return 1;
|
|
@@ -7457,20 +7817,20 @@ function onsetWeightCurve(weight) {
|
|
|
7457
7817
|
}
|
|
7458
7818
|
}
|
|
7459
7819
|
function generateRhythm(ts, opts = {}) {
|
|
7460
|
-
const asked =
|
|
7461
|
-
const meter =
|
|
7820
|
+
const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
|
|
7821
|
+
const meter = _chunkS3QELJUEcjs.meterAt.call(void 0, 0, _chunkS3QELJUEcjs.toMeterData.call(void 0, ts, "ts"));
|
|
7462
7822
|
const bars = _nullishCoalesce(asked.bars, () => ( DEFAULT_BARS));
|
|
7463
7823
|
const subdivision = _nullishCoalesce(asked.subdivision, () => ( DEFAULT_SUBDIVISION));
|
|
7464
7824
|
const ctx = resolveContext(asked.ctx);
|
|
7465
7825
|
const density = _nullishCoalesce(ctx.rhythmic, () => ( DEFAULT_DENSITY));
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
const barBeats =
|
|
7826
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, bars, "rhythm bars");
|
|
7827
|
+
_chunkS3QELJUEcjs.assertPositiveInt.call(void 0, subdivision, "rhythm subdivision");
|
|
7828
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, meter);
|
|
7469
7829
|
const spanBeats = barBeats * bars;
|
|
7470
7830
|
const step = 1 / subdivision;
|
|
7471
7831
|
const slotsPerBar = Math.ceil(barBeats * subdivision);
|
|
7472
7832
|
const slotCount = slotsPerBar * bars;
|
|
7473
|
-
|
|
7833
|
+
_chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, slotCount, "rhythm grid slots");
|
|
7474
7834
|
const draw = ctx.part("rhythm");
|
|
7475
7835
|
const positions = [];
|
|
7476
7836
|
for (let bar2 = 0; bar2 < bars; bar2 += 1) {
|
|
@@ -7485,7 +7845,7 @@ function generateRhythm(ts, opts = {}) {
|
|
|
7485
7845
|
positions.push(position);
|
|
7486
7846
|
continue;
|
|
7487
7847
|
}
|
|
7488
|
-
const weight =
|
|
7848
|
+
const weight = _chunkS3QELJUEcjs.metricWeight.call(void 0, position, meter);
|
|
7489
7849
|
const probability = onsetWeightCurve(weight) * density;
|
|
7490
7850
|
if (draw.prob(probability, "onset", bar2, slot)) {
|
|
7491
7851
|
positions.push(position);
|
|
@@ -7501,13 +7861,13 @@ function generateRhythm(ts, opts = {}) {
|
|
|
7501
7861
|
return events;
|
|
7502
7862
|
}
|
|
7503
7863
|
function rhythmDensity(events, ts) {
|
|
7504
|
-
|
|
7505
|
-
const barBeats =
|
|
7864
|
+
_chunkS3QELJUEcjs.assertArray.call(void 0, events, "events");
|
|
7865
|
+
const barBeats = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts);
|
|
7506
7866
|
if (events.length === 0) {
|
|
7507
7867
|
return 0;
|
|
7508
7868
|
}
|
|
7509
7869
|
const last = events[events.length - 1];
|
|
7510
|
-
const spanBeats = (_nullishCoalesce(_optionalChain([last, 'optionalAccess',
|
|
7870
|
+
const spanBeats = (_nullishCoalesce(_optionalChain([last, 'optionalAccess', _119 => _119.position]), () => ( 0))) + (_nullishCoalesce(_optionalChain([last, 'optionalAccess', _120 => _120.duration]), () => ( 0)));
|
|
7511
7871
|
const bars = spanBeats / barBeats;
|
|
7512
7872
|
return bars > 0 ? events.length / bars : 0;
|
|
7513
7873
|
}
|
|
@@ -7587,5 +7947,9 @@ function rhythmDensity(events, ts) {
|
|
|
7587
7947
|
|
|
7588
7948
|
|
|
7589
7949
|
|
|
7590
|
-
|
|
7591
|
-
|
|
7950
|
+
|
|
7951
|
+
|
|
7952
|
+
|
|
7953
|
+
|
|
7954
|
+
exports.GENRES = GENRES; exports.PROVENANCE_BASES = PROVENANCE_BASES; exports.fitsQuery = fitsQuery; exports.selectVocabulary = selectVocabulary; exports.pickVocabulary = pickVocabulary; exports.mergeVocabulary = mergeVocabulary; exports.vocabularyOfKind = vocabularyOfKind; exports.assertVocabulary = assertVocabulary; exports.MIN_DIFFICULTY = MIN_DIFFICULTY; exports.MAX_DIFFICULTY = MAX_DIFFICULTY; exports.sustainsStrokes = sustainsStrokes; exports.sustainsShift = sustainsShift; exports.resolveContext = resolveContext; exports.BAR_STEPS = BAR_STEPS; exports.BEAT_STEPS = BEAT_STEPS; exports.STEP_BEATS = STEP_BEATS; exports.gridMetricWeight = gridMetricWeight; exports.thin = thin; exports.double = double; exports.halfTime = halfTime; exports.halfTimeFigure = halfTimeFigure; exports.doubleTime = doubleTime; exports.doubleTimeFigure = doubleTimeFigure; exports.syncopate = syncopate; exports.ornamentBy = ornamentBy; exports.deform = deform; exports.resolveDials = resolveDials; exports.deformFigure = deformFigure; exports.withinCeiling = withinCeiling; exports.isLickMaterial = isLickMaterial; exports.BASS_LICKS = BASS_LICKS; exports.placeLicks = placeLicks; exports.BASS_STYLES = BASS_STYLES; exports.generateBassLine = generateBassLine; exports.imitate = imitate; exports.generateCounterMelody = generateCounterMelody; exports.FILL_TYPES = FILL_TYPES; exports.FILL_ARCHETYPES = FILL_ARCHETYPES; exports.isFillArchetype = isFillArchetype; exports.DRUM_NOTES = DRUM_NOTES; exports.drumVoiceOf = drumVoiceOf; exports.KICK_STEPS = KICK_STEPS; exports.KICK_FIGURES = KICK_FIGURES; exports.DRUM_KIT = DRUM_KIT; exports.isDrumPattern = isDrumPattern; exports.DRUM_PATTERNS = DRUM_PATTERNS; exports.placeDrumPattern = placeDrumPattern; exports.generateDrums = generateDrums; exports.humanize = humanize; exports.extractGrooveTemplate = extractGrooveTemplate; exports.applyGrooveTemplate = applyGrooveTemplate; exports.classifyMelodyTones = classifyMelodyTones; exports.harmonizeMelody = harmonizeMelody; exports.cellSpan = cellSpan; exports.generateMotif = generateMotif; exports.motifToNoteEvents = motifToNoteEvents; exports.transformMotif = transformMotif; exports.developMotif = developMotif; exports.COMPOSITION_PLAN_VERSION = COMPOSITION_PLAN_VERSION; exports.assertCompositionPlan = assertCompositionPlan; exports.planTimeline = planTimeline; exports.generateMelody = generateMelody; exports.ORNAMENT_STYLES = ORNAMENT_STYLES; exports.ornament = ornament; exports.deriveCompositionPlan = deriveCompositionPlan; exports.evaluateComposition = evaluateComposition; exports.BORROWED_DEGREES = BORROWED_DEGREES; exports.progressions = progressions; exports.progressionsByStyle = progressionsByStyle; exports.pickProgressionPreset = pickProgressionPreset; exports.generateProgression = generateProgression; exports.substituteChord = substituteChord; exports.modalInterchangePalette = modalInterchangePalette; exports.negativeHarmonyMirror = negativeHarmonyMirror; exports.rhythmToNoteEvents = rhythmToNoteEvents; exports.onsetWeightCurve = onsetWeightCurve; exports.generateRhythm = generateRhythm; exports.rhythmDensity = rhythmDensity;
|
|
7955
|
+
//# sourceMappingURL=chunk-6TTBEON3.cjs.map
|