@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.
Files changed (130) hide show
  1. package/NOTICE +63 -0
  2. package/README.md +3 -1
  3. package/README_ja.md +13 -11
  4. package/dist/analyze/index.cjs +7 -7
  5. package/dist/analyze/index.cjs.map +1 -1
  6. package/dist/analyze/index.d.cts +14 -12
  7. package/dist/analyze/index.d.ts +14 -12
  8. package/dist/analyze/index.js +6 -6
  9. package/dist/{chunk-NB25P3EH.js → chunk-2G5MCGYU.js} +33 -11
  10. package/dist/chunk-2G5MCGYU.js.map +1 -0
  11. package/dist/{chunk-NM7UAMC3.cjs → chunk-3FDBMIPR.cjs} +64 -64
  12. package/dist/chunk-3FDBMIPR.cjs.map +1 -0
  13. package/dist/{chunk-YFA7X2F6.cjs → chunk-3MDOEFIQ.cjs} +411 -327
  14. package/dist/chunk-3MDOEFIQ.cjs.map +1 -0
  15. package/dist/{chunk-IPEF6NWB.js → chunk-5MWRBYAT.js} +278 -154
  16. package/dist/chunk-5MWRBYAT.js.map +1 -0
  17. package/dist/{chunk-B2PW6EHN.cjs → chunk-6TTBEON3.cjs} +1253 -889
  18. package/dist/chunk-6TTBEON3.cjs.map +1 -0
  19. package/dist/{chunk-UMWZ4ZET.js → chunk-7NQ6AL3H.js} +4 -4
  20. package/dist/chunk-7NQ6AL3H.js.map +1 -0
  21. package/dist/{chunk-PWC4CRWT.cjs → chunk-E3QO3UET.cjs} +31 -23
  22. package/dist/chunk-E3QO3UET.cjs.map +1 -0
  23. package/dist/{chunk-GNVN4PPJ.js → chunk-FJFULJZE.js} +531 -213
  24. package/dist/chunk-FJFULJZE.js.map +1 -0
  25. package/dist/{chunk-CPMB7P75.js → chunk-FK3DGAIZ.js} +608 -244
  26. package/dist/chunk-FK3DGAIZ.js.map +1 -0
  27. package/dist/chunk-GEDTJHAC.cjs.map +1 -1
  28. package/dist/{chunk-RFIBF2RR.js → chunk-H7FVMBUC.js} +138 -65
  29. package/dist/chunk-H7FVMBUC.js.map +1 -0
  30. package/dist/{chunk-4R2LWV7E.cjs → chunk-HYSVSFNI.cjs} +664 -540
  31. package/dist/chunk-HYSVSFNI.cjs.map +1 -0
  32. package/dist/{chunk-35NBV2FT.cjs → chunk-KMYGRFZ6.cjs} +47 -24
  33. package/dist/chunk-KMYGRFZ6.cjs.map +1 -0
  34. package/dist/{chunk-IFZDWIKM.cjs → chunk-LQZQDBCD.cjs} +1048 -730
  35. package/dist/chunk-LQZQDBCD.cjs.map +1 -0
  36. package/dist/{chunk-PM4XJE2Y.cjs → chunk-P3CPXAJ5.cjs} +76 -54
  37. package/dist/chunk-P3CPXAJ5.cjs.map +1 -0
  38. package/dist/{chunk-S5BKZZGM.cjs → chunk-S3QELJUE.cjs} +72 -56
  39. package/dist/chunk-S3QELJUE.cjs.map +1 -0
  40. package/dist/{chunk-PUKJP2Z5.js → chunk-TXFWSU5D.js} +31 -8
  41. package/dist/chunk-TXFWSU5D.js.map +1 -0
  42. package/dist/{chunk-76ZBTRG2.cjs → chunk-U4EQTDGN.cjs} +258 -218
  43. package/dist/chunk-U4EQTDGN.cjs.map +1 -0
  44. package/dist/chunk-UGLFDG7L.cjs.map +1 -1
  45. package/dist/{chunk-MLBPXA4Z.js → chunk-UTE5A36R.js} +198 -114
  46. package/dist/chunk-UTE5A36R.js.map +1 -0
  47. package/dist/{chunk-ZBUROTJQ.js → chunk-UZKQISRF.js} +17 -9
  48. package/dist/chunk-UZKQISRF.js.map +1 -0
  49. package/dist/{chunk-7KG3RTYS.js → chunk-VL5NXVCN.js} +281 -155
  50. package/dist/chunk-VL5NXVCN.js.map +1 -0
  51. package/dist/{chunk-CGBADIO5.cjs → chunk-WOMCXN2W.cjs} +328 -202
  52. package/dist/chunk-WOMCXN2W.cjs.map +1 -0
  53. package/dist/{chunk-3R3QVKY5.cjs → chunk-YDGMWH43.cjs} +397 -324
  54. package/dist/chunk-YDGMWH43.cjs.map +1 -0
  55. package/dist/{chunk-AGOVW7U6.js → chunk-YYVXRV3V.js} +72 -56
  56. package/dist/chunk-YYVXRV3V.js.map +1 -0
  57. package/dist/{chunk-M5RYMAFI.js → chunk-ZLNSH4UL.js} +71 -31
  58. package/dist/chunk-ZLNSH4UL.js.map +1 -0
  59. package/dist/{coerce-DRERzdve.d.cts → coerce-CUhHc3Tu.d.ts} +16 -8
  60. package/dist/{coerce-DP0vYu-x.d.ts → coerce-Ytt2Eiq9.d.cts} +16 -8
  61. package/dist/core/index.cjs +5 -5
  62. package/dist/core/index.cjs.map +1 -1
  63. package/dist/core/index.d.cts +9 -8
  64. package/dist/core/index.d.ts +9 -8
  65. package/dist/core/index.js +4 -4
  66. package/dist/generate/index.cjs +8 -8
  67. package/dist/generate/index.cjs.map +1 -1
  68. package/dist/generate/index.d.cts +28 -18
  69. package/dist/generate/index.d.ts +28 -18
  70. package/dist/generate/index.js +7 -7
  71. package/dist/{index-BMweUlm5.d.cts → index-5VJgKz_Q.d.cts} +6 -2
  72. package/dist/{index-BHIUyjhZ.d.ts → index-BLuDesVG.d.ts} +20 -13
  73. package/dist/{index-B9QLziDe.d.cts → index-BV6APVa6.d.cts} +20 -13
  74. package/dist/{index-CL4b4gUQ.d.ts → index-Bf0Sv8a9.d.ts} +6 -2
  75. package/dist/{index-Dw2DP7vm.d.ts → index-BkT21EMv.d.cts} +3 -2
  76. package/dist/{index-BL5N2Oyz.d.cts → index-C7KCaTRz.d.ts} +3 -2
  77. package/dist/{index-Cy15oTvh.d.ts → index-C9MYbuKS.d.cts} +7 -3
  78. package/dist/{index-Cy15oTvh.d.cts → index-C9MYbuKS.d.ts} +7 -3
  79. package/dist/{index-CY-3NVfy.d.cts → index-DVInzCDS.d.cts} +53 -29
  80. package/dist/{index-9eoQs2C1.d.ts → index-Dg-SAfhz.d.ts} +6 -4
  81. package/dist/{index-zaZdmnU4.d.ts → index-jgeug9EA.d.ts} +53 -29
  82. package/dist/{index-cHvbYgJI.d.cts → index-pQihL4z7.d.cts} +6 -4
  83. package/dist/index.cjs +13 -13
  84. package/dist/index.cjs.map +1 -1
  85. package/dist/index.d.cts +11 -11
  86. package/dist/index.d.ts +11 -11
  87. package/dist/index.js +12 -12
  88. package/dist/{masks-Cc7-MzzY.d.ts → masks-BnzXnBj0.d.cts} +3 -2
  89. package/dist/{masks-pADfTOiD.d.cts → masks-tycmkrgs.d.ts} +3 -2
  90. package/dist/model/index.cjs +12 -12
  91. package/dist/model/index.cjs.map +1 -1
  92. package/dist/model/index.d.cts +63 -48
  93. package/dist/model/index.d.ts +63 -48
  94. package/dist/model/index.js +11 -11
  95. package/dist/{positional-DJgs6ltD.d.ts → positional-CscpxtlE.d.cts} +3 -2
  96. package/dist/{positional-DMZer-FM.d.cts → positional-DLnfUgqG.d.ts} +3 -2
  97. package/dist/{profile-DLdlIpS9.d.ts → profile-B4WqcM4H.d.ts} +25 -17
  98. package/dist/{profile-CQMEqdH9.d.cts → profile-BJd1XkPB.d.cts} +25 -17
  99. package/dist/theory/index.cjs +5 -5
  100. package/dist/theory/index.cjs.map +1 -1
  101. package/dist/theory/index.d.cts +18 -14
  102. package/dist/theory/index.d.ts +18 -14
  103. package/dist/theory/index.js +4 -4
  104. package/dist/{types-D-XgxGvp.d.cts → types-7mGFwvMm.d.ts} +45 -22
  105. package/dist/{types-Dh7C064C.d.ts → types-_ofpb2be.d.cts} +45 -22
  106. package/package.json +13 -13
  107. package/dist/chunk-35NBV2FT.cjs.map +0 -1
  108. package/dist/chunk-3R3QVKY5.cjs.map +0 -1
  109. package/dist/chunk-4R2LWV7E.cjs.map +0 -1
  110. package/dist/chunk-76ZBTRG2.cjs.map +0 -1
  111. package/dist/chunk-7KG3RTYS.js.map +0 -1
  112. package/dist/chunk-AGOVW7U6.js.map +0 -1
  113. package/dist/chunk-B2PW6EHN.cjs.map +0 -1
  114. package/dist/chunk-CGBADIO5.cjs.map +0 -1
  115. package/dist/chunk-CPMB7P75.js.map +0 -1
  116. package/dist/chunk-GNVN4PPJ.js.map +0 -1
  117. package/dist/chunk-IFZDWIKM.cjs.map +0 -1
  118. package/dist/chunk-IPEF6NWB.js.map +0 -1
  119. package/dist/chunk-M5RYMAFI.js.map +0 -1
  120. package/dist/chunk-MLBPXA4Z.js.map +0 -1
  121. package/dist/chunk-NB25P3EH.js.map +0 -1
  122. package/dist/chunk-NM7UAMC3.cjs.map +0 -1
  123. package/dist/chunk-PM4XJE2Y.cjs.map +0 -1
  124. package/dist/chunk-PUKJP2Z5.js.map +0 -1
  125. package/dist/chunk-PWC4CRWT.cjs.map +0 -1
  126. package/dist/chunk-RFIBF2RR.js.map +0 -1
  127. package/dist/chunk-S5BKZZGM.cjs.map +0 -1
  128. package/dist/chunk-UMWZ4ZET.js.map +0 -1
  129. package/dist/chunk-YFA7X2F6.cjs.map +0 -1
  130. 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 _chunkCGBADIO5cjs = require('./chunk-CGBADIO5.cjs');
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
- var _chunkS5BKZZGMcjs = require('./chunk-S5BKZZGM.cjs');
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, draw, name);
142
+ const sampler = _chunkS3QELJUEcjs.assertRecord.call(void 0, draw, name);
139
143
  for (const method of DRAW_METHODS) {
140
- _chunkS5BKZZGMcjs.assertFunction.call(void 0, sampler[method], `${name}.${method}`);
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 = _chunkS5BKZZGMcjs.assertArray.call(void 0, path, name);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
150
- `${name}[${index}] must be a string or a finite number; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, step)}`
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, _chunkS5BKZZGMcjs.InvalidInputError)(`positional draw must be in [0, 1); received ${draw}`);
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) => _chunkCGBADIO5cjs.includeAt.call(void 0, rng, p, ...prefix, ...path),
171
+ prob: (p, ...path) => _chunkWOMCXN2Wcjs.includeAt.call(void 0, rng, p, ...prefix, ...path),
168
172
  range: (lo, hi, ...path) => {
169
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, lo, "range lower bound");
170
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, hi, "range upper bound");
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, _chunkS5BKZZGMcjs.InvalidInputError)(
176
+ throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
173
177
  `range lower bound must not exceed upper bound; received ${lo} > ${hi}`
174
178
  );
175
179
  }
176
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, hi - lo, "range span", 0);
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, lo, "float lower bound");
181
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, hi, "float upper bound");
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, _chunkS5BKZZGMcjs.InvalidInputError)(
187
+ throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
184
188
  `float lower bound must not exceed upper bound; received ${lo} > ${hi}`
185
189
  );
186
190
  }
187
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, hi - lo, "float span");
188
- return lo + at2(...path) * (hi - lo);
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
- return a.numerator === b.numerator && a.denominator === b.denominator;
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, entry, "vocabulary entry");
417
- const asked = _chunkS5BKZZGMcjs.assertRecord.call(void 0, query, "vocabulary query");
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, _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, asked.ts, "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 _chunkS5BKZZGMcjs.assertArray.call(void 0, dictionary, "dictionary").filter(
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 = _chunkS5BKZZGMcjs.assertArray.call(void 0, builtIn, "builtIn");
460
- const extra = supplied === void 0 || supplied === null ? [] : _chunkS5BKZZGMcjs.assertArray.call(void 0, supplied, "supplied");
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) => _chunkS5BKZZGMcjs.assertRecord.call(void 0, entry, `${side}[${index}]`).id;
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 = _chunkS5BKZZGMcjs.assertFunction.call(void 0, isMaterial, "isMaterial");
478
- for (const entry of _chunkS5BKZZGMcjs.assertArray.call(void 0, entries, "entries")) {
479
- if (recognises(_chunkS5BKZZGMcjs.assertRecord.call(void 0, entry, "entry").material)) {
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, _chunkS5BKZZGMcjs.InvalidInputError)(
488
- `${label} must be an array of names; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, values)}`
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
- _chunkS5BKZZGMcjs.assertOneOf.call(void 0, value, allowed, `${label}[${index}]`);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
498
- `${label} must be a dictionary entry; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, entry)}`
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
- _chunkS5BKZZGMcjs.assertOneOf.call(void 0, entry.genre, GENRES, `${label} genre`);
502
- _chunkS5BKZZGMcjs.assertOneOf.call(void 0, _optionalChain([entry, 'access', _2 => _2.provenance, 'optionalAccess', _3 => _3.basis]), PROVENANCE_BASES, `${label} provenance basis`);
503
- assertNames(entry.articulations, _chunkS5BKZZGMcjs.ARTICULATIONS, `${label} 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, _chunk3R3QVKY5cjs.chordQualities.call(void 0, ), `${label} fitsOver`);
514
+ assertNames(entry.fitsOver, _chunkYDGMWH43cjs.chordQualities.call(void 0, ), `${label} fitsOver`);
509
515
  }
510
516
  if (entry.ts !== void 0) {
511
- _chunkS5BKZZGMcjs.assertTimeSignature.call(void 0, entry.ts, `${label} ts`);
517
+ _chunkS3QELJUEcjs.assertTimeSignature.call(void 0, entry.ts, `${label} ts`);
512
518
  }
513
- _chunkS5BKZZGMcjs.assertRange.call(void 0, entry.difficulty, 1, 5, `${label} difficulty`);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
517
- `${label} tempoRange must be a low and a high tempo; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, entry.tempoRange)}`
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
- _chunkS5BKZZGMcjs.assertRange.call(void 0, low, Number.MIN_VALUE, 1e3, `${label} tempoRange low`);
522
- _chunkS5BKZZGMcjs.assertRange.call(void 0, high, low, 1e3, `${label} tempoRange high`);
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 _chunkS5BKZZGMcjs.assertRange.call(void 0, difficulty, MIN_DIFFICULTY, MAX_DIFFICULTY, label);
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, bpm, "bpm");
552
- if (_chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, stepBeats, "stepBeats") <= 0) {
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, bpm, "bpm");
564
- _chunkS5BKZZGMcjs.assertFiniteSemitones.call(void 0, semitones);
565
- if (_chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, stepBeats, "stepBeats") <= 0) {
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
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, input, "ctx");
591
+ _chunkS3QELJUEcjs.assertRecord.call(void 0, input, "ctx");
578
592
  }
579
593
  if (input === null) {
580
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)("ctx must be a seed or a generation context; received null");
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 = _chunkS5BKZZGMcjs.assertInteger.call(void 0, _nullishCoalesce(ctx.seed, () => ( DEFAULT_SEED)), "seed", 0, 4294967295);
584
- const complexity = _nullishCoalesce(ctx.complexity, () => ( {}));
585
- const rhythmic = complexity.rhythmic === void 0 ? void 0 : _chunkS5BKZZGMcjs.assertRange.call(void 0, complexity.rhythmic, 0, 1, "complexity rhythmic");
586
- const harmonic = complexity.harmonic === void 0 ? void 0 : _chunkS5BKZZGMcjs.assertRange.call(void 0, complexity.harmonic, 0, 1, "complexity harmonic");
587
- const ornament2 = complexity.ornament === void 0 ? void 0 : _chunkS5BKZZGMcjs.assertRange.call(void 0, complexity.ornament, 0, 1, "complexity ornament");
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 : _chunkS5BKZZGMcjs.assertRange.call(void 0, ctx.bpm, Number.MIN_VALUE, 1e3, "bpm");
590
- const algorithmVersion = _chunkCGBADIO5cjs.resolveAlgorithmVersion.call(void 0, ctx.algorithmVersion);
591
- const supplied = ctx.rng;
592
- const instruments = ctx.instruments;
593
- const vocabulary = (_nullishCoalesce(ctx.vocabulary, () => ( []))).map(
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) => _optionalChain([instruments, 'optionalAccess', _4 => _4[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(_chunkCGBADIO5cjs.createPositionalRng.call(void 0, _chunkCGBADIO5cjs.deriveSeed.call(void 0, seed, name, VERSION_SEGMENT, algorithmVersion)))
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 : _chunkS5BKZZGMcjs.assertRange.call(void 0, sugar.ornament, 0, 1, "complexity ornament");
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 + _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, pc - low);
640
+ return low + _chunkS3QELJUEcjs.pitchClassOf.call(void 0, pc - low);
629
641
  }
630
642
  function barTiles(startBeat, endBeat, ts) {
631
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, ts);
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 = _chunkS5BKZZGMcjs.pulseBeats.call(void 0, ts);
644
- return barStart + Math.floor((_chunkS5BKZZGMcjs.beatsPerBar.call(void 0, ts) / 2 + _chunkS5BKZZGMcjs.BEAT_EPS) / pulse2) * pulse2;
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
- _chunkS5BKZZGMcjs.assertRange.call(void 0, segment.startBeat, 0, Number.MAX_SAFE_INTEGER, `segments[${index}].startBeat`);
653
- _chunkS5BKZZGMcjs.assertRange.call(void 0, segment.endBeat, 0, Number.MAX_SAFE_INTEGER, `segments[${index}].endBeat`);
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, _chunkS5BKZZGMcjs.InvalidInputError)(`segments[${index}] must have a positive duration`);
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
659
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(
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 = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc + interval);
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(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc));
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(_chunk3R3QVKY5cjs.fifthPcOf.call(void 0, chord), () => ( _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc)));
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 _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, _nullishCoalesce(chord.bassPc, () => ( chord.rootPc)));
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 = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, ts);
695
- const pulse2 = _chunkS5BKZZGMcjs.pulseBeats.call(void 0, ts);
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 - _chunkS5BKZZGMcjs.BEAT_EPS) / barBeats);
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 - _chunkS5BKZZGMcjs.BEAT_EPS) / pulse2));
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 - _chunkS5BKZZGMcjs.BEAT_EPS || position >= end - _chunkS5BKZZGMcjs.BEAT_EPS) {
715
+ if (position >= barStart + barBeats - _chunkS3QELJUEcjs.BEAT_EPS || position >= end - _chunkS3QELJUEcjs.BEAT_EPS) {
704
716
  break;
705
717
  }
706
- if (position >= start - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 = _chunkCGBADIO5cjs.instrumentRange.call(void 0, instrument);
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 = _chunk3R3QVKY5cjs.nearestScaleTone.call(void 0, target + dir * 2, key);
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 : _chunkCGBADIO5cjs.toStringedProfile.call(void 0, given, "instrument");
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
- _chunkS5BKZZGMcjs.assertArray.call(void 0, events, "figure events");
770
+ _chunkS3QELJUEcjs.assertArray.call(void 0, events, "figure events");
758
771
  events.forEach((event, index) => {
759
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, event, `figure events[${index}]`);
760
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, event.step, `figure events[${index}].step`);
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 _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, spanSteps, "figure span steps");
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 = _chunkS5BKZZGMcjs.pulseBeats.call(void 0, ts);
773
- return _chunkS5BKZZGMcjs.isCompound.call(void 0, ts) ? pulse2 / 3 : pulse2 / 2;
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, step, "step");
777
- return stepWeight(step, _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, ts, "ts")));
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 = _chunkS5BKZZGMcjs.metricWeight.call(void 0, beats, ts);
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
- _chunkS5BKZZGMcjs.assertRange.call(void 0, amount, 0, 1, "thin amount");
792
- const signature = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, ts, "ts"));
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, signature) >= floor);
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 out = [];
800
- for (let i = 0; i < sorted.length; i += 1) {
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
- if (!event) {
803
- continue;
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(_optionalChain([sorted, 'access', _5 => _5[i + 1], 'optionalAccess', _6 => _6.step]), () => ( spanSteps));
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).map((event) => ({ ...event, step: event.step * 2 })).filter((event) => event.step < spanSteps);
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 = `${streamOf(event)}@${step}`;
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 events) {
831
- const step = Math.round(event.step / 2);
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 : _chunkS5BKZZGMcjs.assertRecord.call(void 0, amount, "amount");
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 = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(_optionalChain([asked, 'optionalAccess', _7 => _7.ts]), () => ( FIGURE_TS)), "ts"));
847
- _chunkS5BKZZGMcjs.assertRange.call(void 0, dial, 0, 1, "syncopate amount");
848
- const occupied = new Set(figure.map((event) => `${streamOf(event)}@${event.step}`));
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, signature) < 2 || anticipated < 1 || occupied.has(`${streamOf(event)}@${anticipated}`)) {
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.step)) {
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 = _chunkS5BKZZGMcjs.assertFunction.call(void 0, isOrnament, "isOrnament");
901
+ const marks = _chunkS3QELJUEcjs.assertFunction.call(void 0, isOrnament, "isOrnament");
865
902
  const sampler = assertDraw(draw);
866
903
  assertSeedPath(path);
867
- _chunkS5BKZZGMcjs.assertRange.call(void 0, amount, 0, 1, "ornament amount");
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.step)
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "opts");
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
- const ts = _nullishCoalesce(asked.ts, () => ( FIGURE_TS));
880
- let out = asked.rate === "half" ? halfTime(figure, spanSteps) : asked.rate === "double" ? doubleTime(figure, spanSteps) : [...figure];
881
- if (asked.rhythmic !== void 0) {
882
- const rhythmic = _chunkS5BKZZGMcjs.assertRange.call(void 0, asked.rhythmic, 0, 1, "complexity rhythmic");
883
- if (rhythmic < NEUTRAL_RHYTHMIC) {
884
- out = thin(out, (NEUTRAL_RHYTHMIC - rhythmic) / NEUTRAL_RHYTHMIC, ts);
885
- } else if (rhythmic > NEUTRAL_RHYTHMIC) {
886
- out = syncopate(
887
- out,
888
- { amount: (rhythmic - NEUTRAL_RHYTHMIC) / NEUTRAL_RHYTHMIC, ts },
889
- draw,
890
- ...path
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
- if (asked.ornament !== void 0 && asked.isOrnament) {
895
- const isOrnament = _chunkS5BKZZGMcjs.assertFunction.call(void 0, asked.isOrnament, "opts.isOrnament");
896
- out = ornamentBy(out, (event) => isOrnament(event), asked.ornament, draw, ...path);
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, bpm, "bpm");
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 _chunkPM4XJE2Ycjs.chordScales.call(void 0, chord)) {
944
- const mask = _chunk3R3QVKY5cjs.namedScaleMask.call(void 0, match.name);
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) => _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, interval) === semitones);
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', _8 => _8[within - 1]]))), () => ( // A degree neither the chord nor its quality settles is a passing tone,
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
- _chunk3R3QVKY5cjs.nearestScaleTone.call(void 0, chord.rootPc + template, key) - chord.rootPc));
977
- return _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, semitone) + 12 * octaves + alter;
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 (_chunk3R3QVKY5cjs.degreeOfInterval.call(void 0, interval, chord) === degree) {
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "opts");
1212
- const placement = _chunkS5BKZZGMcjs.assertArray.call(void 0,
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, placement.length, "lick segments", asked.budget);
1217
- const genre = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, asked.genre, GENRES, "lick genre");
1218
- const ts = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(asked.ts, () => ( DEFAULT_TS)), "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
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, octave, "lick octave", -1, 8);
1221
- const scale = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key);
1222
- const segments = placement.map((segment) => ({ ...segment, chord: _chunk3R3QVKY5cjs.toChordData.call(void 0, segment.chord) })).sort((a, b) => a.startBeat - b.startBeat);
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 = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, ts);
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, estimatedBars, "lick bars", asked.budget);
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 dictionary = mergeVocabulary(
1241
- BASS_LICKS,
1242
- vocabularyOfKind(resolved.vocabulary, isLickMaterial)
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', _9 => _9[tile], 'optionalAccess', _10 => _10.startBeat]), () => ( segment.startBeat));
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(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, segment.chord.rootPc), rootMidi, low) : placeAboveBass(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, segment.chord.rootPc), rootMidi);
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) < _chunkS5BKZZGMcjs.BEAT_EPS && lickNote.degree === 1 && (_nullishCoalesce(lickNote.alter, () => ( 0))) === 0 ? rootMidi : figureRoot + offset;
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
- (_chunkS5BKZZGMcjs.isStrongBeat.call(void 0, at2, ts) ? STRONG_VELOCITY : WEAK_VELOCITY) * lickNote.velocity
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 + _chunkS5BKZZGMcjs.BEAT_EPS) {
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', _11 => _11[i + 1], 'optionalAccess', _12 => _12.startBeat]), () => ( lastEnd));
1343
- const written = _optionalChain([item, 'access', _13 => _13.note, 'optionalAccess', _14 => _14.lengthSteps]);
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 <= _chunkS5BKZZGMcjs.BEAT_EPS) {
1424
+ if (durationBeat <= _chunkS3QELJUEcjs.BEAT_EPS) {
1349
1425
  continue;
1350
1426
  }
1351
- const placed = instrument ? _chunkCGBADIO5cjs.foldIntoRange.call(void 0, item.pitch, instrument) : item.pitch;
1427
+ const placed = instrument ? _chunkWOMCXN2Wcjs.foldIntoRange.call(void 0, item.pitch, instrument) : item.pitch;
1352
1428
  const event = {
1353
- pitch: _chunkS5BKZZGMcjs.clampToMidi.call(void 0, placed, "generated bass 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', _15 => _15.note, 'optionalAccess', _16 => _16.articulation])) {
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) < _chunkS5BKZZGMcjs.BEAT_EPS) {
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 - _chunkS5BKZZGMcjs.BEAT_EPS || at2 > to - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 - _chunkS5BKZZGMcjs.BEAT_EPS);
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 ? _chunkCGBADIO5cjs.foldIntoRange.call(void 0, placed, ctx.instrument) : placed;
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 = _chunkS5BKZZGMcjs.clampToMidi.call(void 0, _nullishCoalesce(midiOverride, () => ( placeTone(ctx, pc))), "generated bass pitch");
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 = _chunkS5BKZZGMcjs.isStrongBeat.call(void 0, pos, ctx.ts) ? STRONG_VELOCITY : WEAK_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 + _chunkS5BKZZGMcjs.BEAT_EPS && answer < tile.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 (_chunkS5BKZZGMcjs.isStrongBeat.call(void 0, pos, ctx.ts)) {
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, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, midi), midi);
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
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "bass line options");
1549
- _chunkS5BKZZGMcjs.assertArray.call(void 0, opts.segments, "bass segments");
1550
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, opts.segments.length, "bass segments", opts.budget);
1551
- const segments = opts.segments.map((segment) => ({ ...segment, chord: _chunk3R3QVKY5cjs.toChordData.call(void 0, segment.chord) })).sort((a, b) => a.startBeat - b.startBeat);
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 = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_TS)), "ts"));
1557
- const style = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.style, () => ( DEFAULT_STYLE)), BASS_STYLES, "bass 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
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, octave, "bass octave", -1, 8);
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, estimatedNotes, "bass notes", opts.budget);
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: _chunk3R3QVKY5cjs.toKeyScale.call(void 0, opts.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', _17 => _17.notes, 'access', _18 => _18[i + 1], 'optionalAccess', _19 => _19.startBeat]), () => ( lastEnd));
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 <= _chunkS5BKZZGMcjs.BEAT_EPS) {
1692
+ if (durationBeat <= _chunkS3QELJUEcjs.BEAT_EPS) {
1617
1693
  continue;
1618
1694
  }
1619
1695
  out.push({
1620
- pitch: _chunkS5BKZZGMcjs.clampToMidi.call(void 0, note2.pitch, "generated bass 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, _chunkS5BKZZGMcjs.InvalidInputError)(`imitated pitch ${pitch} is outside the MIDI range 0..127`);
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
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, lead, "imitate lead", { allowNonPositiveDuration: true });
1643
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "opts");
1644
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, opts.atBeat, "atBeat");
1645
- const interval = _chunkS5BKZZGMcjs.toSpelledInterval.call(void 0, opts.interval);
1646
- const key = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, opts.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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, opts.from, "from");
1726
+ _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, opts.from, "from");
1651
1727
  }
1652
1728
  if (opts.to !== void 0) {
1653
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, opts.to, "to");
1729
+ _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, opts.to, "to");
1654
1730
  }
1655
1731
  if (from > to) {
1656
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`imitate needs from <= to; received ${from} > ${to}`);
1732
+ throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(`imitate needs from <= to; received ${from} > ${to}`);
1657
1733
  }
1658
1734
  const velocityScale = _nullishCoalesce(opts.velocityScale, () => ( 1));
1659
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, velocityScale, "velocityScale");
1660
- const tonal = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.answer, () => ( "real")), IMITATION_ANSWERS, "imitate answer") === "tonal";
1661
- const subject = _chunkS5BKZZGMcjs.dropSilentNotes.call(void 0, lead).filter((note2) => note2.startBeat >= from && note2.startBeat < to).sort((a, b) => a.startBeat - b.startBeat);
1662
- const origin = _optionalChain([subject, 'access', _20 => _20[0], 'optionalAccess', _21 => _21.startBeat]);
1663
- const pivot = _optionalChain([subject, 'access', _22 => _22[0], 'optionalAccess', _23 => _23.pitch]);
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 here = _chunk3R3QVKY5cjs.scaleLadderPosition.call(void 0, pitch, key);
1676
- pitch = _chunk3R3QVKY5cjs.scaleLadderPitch.call(void 0, 2 * _chunk3R3QVKY5cjs.scaleLadderPosition.call(void 0, pivot, key).rung - here.rung, key);
1677
- offset = -here.offset;
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 ? _chunk3R3QVKY5cjs.shiftByScaleDegrees.call(void 0, pitch, degrees, key) + offset : pitch + Math.round(interval.semitones);
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)) < _chunkS5BKZZGMcjs.BEAT_EPS;
1784
+ return Math.abs(beat - Math.round(beat)) < _chunkS3QELJUEcjs.BEAT_EPS;
1708
1785
  }
1709
1786
  function melodyNoteAt(melody, beat) {
1710
- return _optionalChain([melody, 'access', _24 => _24.at, 'call', _25 => _25(beat), 'optionalAccess', _26 => _26.note]);
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) < _chunkS5BKZZGMcjs.BEAT_EPS;
1721
- const previous = attacked ? melodyNoteAt(melody, beat - _chunkS5BKZZGMcjs.BEAT_EPS * 2) : current;
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 - _chunkS5BKZZGMcjs.BEAT_EPS; beat += GRID_STEP) {
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 (_chunkS5BKZZGMcjs.isStrongBeat.call(void 0, beat, ts)) {
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
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, _chunkS5BKZZGMcjs.InvalidInputError)(
1770
- `countermelody weights must be an object of weight overrides; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, overrides)}`
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, value, `countermelody weights.${field}`);
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 && _chunk3R3QVKY5cjs.chordToneRole.call(void 0, pitch, chord) !== null) {
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 (_chunk3R3QVKY5cjs.isForbiddenMelodicLeap.call(void 0, prevPitch, pitch)) {
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 + _chunkS5BKZZGMcjs.BEAT_EPS && beat < endBeat - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 - _chunkS5BKZZGMcjs.BEAT_EPS; beat += GRID_STEP) {
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: _chunkS5BKZZGMcjs.isStrongBeat.call(void 0, boundary, ts),
1843
- atCounterOnset: Math.abs(boundary - startBeat) < _chunkS5BKZZGMcjs.BEAT_EPS
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 = _chunk3R3QVKY5cjs.evaluateSafety.call(void 0,
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
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "countermelody options");
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, _chunkS5BKZZGMcjs.InvalidInputError)("countermelody needs a timeline or a chordAt callback");
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
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, opts.melody, "countermelody melody", { allowNonPositiveDuration: true });
1885
- const melody = _chunk35NBV2FTcjs.createNoteEventIndex.call(void 0, _chunkS5BKZZGMcjs.soundingNotesOnly.call(void 0, opts.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 = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_TS2)), "ts"));
1889
- _chunkS5BKZZGMcjs.assertTimeSignature.call(void 0, ts);
1890
- const rhythm = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.rhythm, () => ( "complement")), ["complement", "follow"], "rhythm");
1891
- const profile = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, _nullishCoalesce(opts.profile, () => ( "pop")), ["strict", "pop"], "safety 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 = _chunk3R3QVKY5cjs.profileWeights.call(void 0, profile, opts.weights);
1894
- const key = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, opts.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', _27 => _27.notes, 'access', _28 => _28[0], 'optionalAccess', _29 => _29.note, 'access', _30 => _30.startBeat]), () => ( 0));
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, Math.ceil((spanEnd - spanStart) / GRID_STEP), "countermelody grid");
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 = _chunkS5BKZZGMcjs.clampToMidi.call(void 0,
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 = _chunkS5BKZZGMcjs.clampToMidi.call(void 0,
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, _chunkS5BKZZGMcjs.InvalidInputError)(
1990
+ throw new (0, _chunkS3QELJUEcjs.InvalidInputError)(
1914
1991
  `countermelody pitchLow must not exceed pitchHigh; received ${low} > ${high}`
1915
1992
  );
1916
1993
  }
1917
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, high - low + 1, "countermelody pitch candidates");
1918
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, chordChangeBeats.length, "chord change beats");
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
- _chunkS5BKZZGMcjs.assertRange.call(void 0,
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, boundaryEstimate * (high - low + 1), "countermelody search");
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', _31 => _31.pitch]);
2022
+ const melPitch = _optionalChain([melNote, 'optionalAccess', _28 => _28.pitch]);
1946
2023
  const melodyVoice = melodySnapshotAt(melody, beat);
1947
- const melPrev = _optionalChain([melodyVoice, 'optionalAccess', _32 => _32.prevPitch]);
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', _33 => _33[0], 'optionalAccess', _34 => _34.chord]), () => ( chordAt(beat)));
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 = _chunk3R3QVKY5cjs.enumerateSafePitches.call(void 0,
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: _chunkS5BKZZGMcjs.isStrongBeat.call(void 0, beat, ts),
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
- _chunk3R3QVKY5cjs.createsParallelPerfect.call(void 0, prevPitch, candidate, melPrev, melPitch)) {
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', _35 => _35.velocity]), () => ( DEFAULT_MELODY_VELOCITY))) - VELOCITY_DROP))
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: _chunkS5BKZZGMcjs.clampToMidi.call(void 0, 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 getHiHatLevel(section, style, rhythmic, bpm, draw, difficulty, bar2) {
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
- if (draw.at("hhThin", bar2) >= 2 * rhythmic) {
2251
+ const thin2 = draw.at("hhThin", bar2);
2252
+ if (thin2 >= 2 * rhythmic) {
2165
2253
  level = sparser(level);
2166
2254
  }
2167
- if (draw.at("hhFill", bar2) < 2 * rhythmic - 1) {
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
- if (!allow16th && level === "sixteenth") {
2172
- level = "eighth";
2173
- }
2174
- while (level !== "quarter" && !sustainsStrokes(hiHatStep(level), bpm, difficulty)) {
2175
- level = sparser(level);
2176
- }
2177
- return level;
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
- if (!kick[index]) {
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
- let ghostProb = leanedBy(getGhostDensity(sec.ghostMood, ctx.section, ctx.bpm), sec.ornament);
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
- if (!ctx.draw.prob(ghostProb * posProb, "ghost", ctx.bar, ctx.beat, pos)) {
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(hiHatNote("open"), ctx.beatTick, EIGHTH, Math.max(20, hhVel * 1.1));
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(GM.FHH, hhTick, EIGHTH, footHiHatVelocity(ctx.draw, ctx.bar, ctx.beat));
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(hiHatNote("open"), hhTick, EIGHTH, Math.max(20, hhVel * 1.1));
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(hiHatNote("open"), hhTick, SIXTEENTH, Math.max(20, hhVel * 1.1));
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(hiHatNote("open"), hhTick, SIXTEENTH, Math.max(20, hhVel * 1.1));
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
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, steps, "euclidean steps");
2605
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, pulses, "euclidean pulses");
2606
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, rotation, "euclidean rotation");
2607
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, steps, "euclidean pattern steps");
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
- while (remainder.length > 1) {
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', _36 => _36.get, 'call', _37 => _37(id)]), () => ( FILL_ARCHETYPES[id]));
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(_chunkS5BKZZGMcjs.assertMidiPitch.call(void 0, pitch));
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', _38 => _38.#onsets, 'access', _39 => _39.get, 'call', _40 => _40(beatSlot(startBeat)), 'optionalAccess', _41 => _41.has, 'call', _42 => _42(pitch)]), () => ( false));
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 realiseKickFigure(figure, section, bar2, draw, rhythmic) {
3086
- const pattern = emptyPattern();
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
- pattern[slot.step] = true;
3278
+ entries[slot.step] = Number.NEGATIVE_INFINITY;
3099
3279
  continue;
3100
3280
  }
3101
- if (draw.prob(leanedBy(slot.probability, rhythmic), "kick", bar2, _nullishCoalesce(slot.slot, () => ( slot.step)))) {
3102
- pattern[slot.step] = true;
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 pattern;
3289
+ return entries;
3106
3290
  }
3107
- function getKickPattern(section, style, bar2, draw, rhythmic) {
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 realiseKickFigure(figure, section, bar2, draw, rhythmic);
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', _43 => _43[sectionIndex(section)]]), () => ( F));
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 = [0.75, 0.45, 0.6, 0.45];
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
- if (sub % 2 === 1 && !draw.prob(sec.rhythmic, "shaker16", barStart, beat, sub)) {
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 = [0.75, 0.55];
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: _chunkCGBADIO5cjs.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: _chunkCGBADIO5cjs.LIMBS.length + OVERDUB_VOICES.length
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, _chunkS5BKZZGMcjs.InvalidInputError)(
3271
- `${label} strokes[${index}].voice must name a drum voice; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, _optionalChain([stroke, 'optionalAccess', _44 => _44.voice]))}`
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
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "drum pattern options");
3464
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, opts.bars, "drum pattern bars");
3465
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, opts.bars * MAX_STROKES_PER_BAR, "drum pattern hits", opts.budget);
3466
- const genre = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.genre, GENRES, "drum pattern genre");
3467
- const section = opts.section === void 0 ? void 0 : _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.section, PUBLIC_SECTIONS, "drum pattern section");
3468
- const ts = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( FOUR_FOUR2)), "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
- _chunkS5BKZZGMcjs.assertRange.call(void 0, opts.velocity, 1, 127, "drum pattern velocity");
3659
+ _chunkS3QELJUEcjs.assertRange.call(void 0, opts.velocity, 1, 127, "drum pattern velocity");
3471
3660
  }
3472
- const feel = opts.feel === void 0 ? "straight" : _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.feel, DRUM_FEELS, "feel");
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 = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, ts);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
3487
- `drum pattern ts names a meter no figure is written in: ${_chunkS5BKZZGMcjs.formatTimeSignature.call(void 0, ts)}. The built-in figures are written in 4/4; supply vocabulary in another meter through the context.`
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: _nullishCoalesce(opts.rate, () => ( "straight")),
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 || _chunkCGBADIO5cjs.canSound.call(void 0, kit, h.pitch))).sort((a, b) => a.startBeat - b.startBeat || a.pitch - b.pitch);
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
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "drum options");
3560
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, opts.bars, "drum bars");
3561
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, opts.bars * MAX_HITS_PER_BAR, "drum hits", opts.budget);
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
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, steps, "euclidean steps", 1, 16);
3565
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, opts.euclideanKick.pulses, "euclidean pulses");
3566
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, _nullishCoalesce(opts.euclideanKick.rotation, () => ( 0)), "euclidean rotation");
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 = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.style, GROOVE_STYLES, "drum style");
3569
- const publicSection = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.section, PUBLIC_SECTIONS, "drum section");
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
- _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.nextSection, PUBLIC_SECTIONS, "drum nextSection");
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 : _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.feel, DRUM_FEELS, "drum feel");
3583
- const role = opts.role === void 0 ? "full" : _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.role, DRUM_ROLES, "drum role");
3584
- const meters = _chunkS5BKZZGMcjs.resolveMeters.call(void 0, { ts: opts.ts }, "ts");
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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 = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, meters);
3593
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, ts);
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 callerFillEntries = selectVocabulary(
3621
- vocabularyOfKind(resolved.vocabulary, isFillArchetype),
3622
- { section: publicSection, bpm, difficulty }
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', _45 => _45.euclideanKick, 'optionalAccess', _46 => _46.steps]), () => ( 16));
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 hhLevel = getHiHatLevel(section, style, rhythmic, bpm, draw, difficulty, bar2);
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 ??= getKickPattern(section, style, 0, draw, rhythmic);
3842
+ sectionKick ??= getKickEntries(section, style, 0, draw, rhythmic);
3647
3843
  kick = sectionKick;
3648
3844
  } else if (!euclidKick) {
3649
- kick = getKickPattern(section, style, bar2, draw, rhythmic);
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 lastOnset = /* @__PURE__ */ new Map();
3773
- const kept = [];
3774
- for (const hit2 of hits) {
3775
- const previous = lastOnset.get(hit2.pitch);
3776
- const reachable = previous === void 0 || exempt.has(onsetKey(hit2.pitch, hit2.startBeat)) || sustainsStrokes(hit2.startBeat - previous, bpm, difficulty);
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.push(hit2);
3781
- lastOnset.set(hit2.pitch, hit2.startBeat);
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 || _chunkCGBADIO5cjs.canSound.call(void 0, kit, pitch);
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 = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
3802
- const ts = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(asked.ts, () => ( DEFAULT_TS3)), "ts"));
3803
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, events, "humanize events", { allowNonPositiveDuration: true });
3804
- const sounding2 = _chunkS5BKZZGMcjs.dropSilentNotes.call(void 0, events);
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
- _chunkS5BKZZGMcjs.assertRange.call(void 0, timing, 0, Number.MAX_SAFE_INTEGER, "humanize timing");
3810
- _chunkS5BKZZGMcjs.assertRange.call(void 0, velocityJitter, 0, 127, "humanize velocity jitter");
3811
- _chunkS5BKZZGMcjs.assertRange.call(void 0, accent2, 0, 127, "humanize accent");
3812
- _chunkS5BKZZGMcjs.assertRange.call(void 0, baseVelocity, 0, 127, "humanize base velocity");
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 = _chunkS5BKZZGMcjs.metricWeight.call(void 0, event.startBeat, ts);
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 = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, ts, "ts"));
3848
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, events, "groove source events", { allowNonPositiveDuration: true });
3849
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, subdivision, "groove subdivision");
3850
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, meter);
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
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, slotsPerBar, "groove template slots");
3853
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, slotsPerBar, "groove template slots");
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 _chunkS5BKZZGMcjs.dropSilentNotes.call(void 0, events)) {
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 = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, ts, "ts"));
3889
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, events, "groove target events", { allowNonPositiveDuration: true });
3890
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, template.subdivision, "template subdivision");
3891
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, template.slotsPerBar, "template slotsPerBar");
3892
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, template.slots.length, "template slots");
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, _chunkS5BKZZGMcjs.InvalidInputError)("template slots length must equal slotsPerBar");
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, _chunkS5BKZZGMcjs.InvalidInputError)(
3898
- `Groove template meter ${_chunkS5BKZZGMcjs.formatTimeSignature.call(void 0, template.ts)} does not match apply-time meter ${_chunkS5BKZZGMcjs.formatTimeSignature.call(void 0, 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 = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, meter);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
3905
- `Groove template slotsPerBar ${template.slotsPerBar} does not match ${expectedSlots} slots per bar of ${_chunkS5BKZZGMcjs.formatTimeSignature.call(void 0, meter)} at subdivision ${template.subdivision}`
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, slot.timingOffset, `template slots[${index}].timingOffset`);
4145
+ _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, slot.timingOffset, `template slots[${index}].timingOffset`);
3914
4146
  if (slot.velocity !== null && slot.velocity !== void 0) {
3915
- _chunkS5BKZZGMcjs.assertRange.call(void 0, slot.velocity, 0, 127, `template slots[${index}].velocity`);
4147
+ _chunkS3QELJUEcjs.assertRange.call(void 0, slot.velocity, 0, 127, `template slots[${index}].velocity`);
3916
4148
  }
3917
4149
  }
3918
- return _chunkS5BKZZGMcjs.dropSilentNotes.call(void 0, events).map((event) => {
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', _47 => _47.timingOffset]), () => ( 0)));
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) <= _chunkIFZDWIKMcjs.HUMANIZE_ADJACENCY ? 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 = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, ts, "ts"));
3950
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, melody, "melody notes", { allowNonPositiveDuration: true });
3951
- const pulse2 = _chunkS5BKZZGMcjs.pulseBeats.call(void 0, meter);
3952
- return melody.map((_, index) => {
3953
- const role = roleOfNote(melody, index, meter, pulse2);
3954
- return { noteIndex: index, role, ornamental: role !== "structural" };
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(melody, index, ts, pulse2) {
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 > _chunkIFZDWIKMcjs.HUMANIZE_ADJACENCY || outOfNote > _chunkIFZDWIKMcjs.HUMANIZE_ADJACENCY) {
4210
+ if (intoNote > _chunkLQZQDBCDcjs.HUMANIZE_ADJACENCY || outOfNote > _chunkLQZQDBCDcjs.HUMANIZE_ADJACENCY) {
3967
4211
  return "structural";
3968
4212
  }
3969
- const weight = _chunkS5BKZZGMcjs.metricWeight.call(void 0, snapToPulse(note2.startBeat, pulse2), ts);
3970
- const weightPrev = _chunkS5BKZZGMcjs.metricWeight.call(void 0, snapToPulse(prev.startBeat, pulse2), ts);
3971
- const weightNext = _chunkS5BKZZGMcjs.metricWeight.call(void 0, snapToPulse(next.startBeat, pulse2), ts);
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: _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, _chunk3R3QVKY5cjs.makeChord.call(void 0, 0, "maj"))
4247
+ pcs: _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, 0, "maj"))
4004
4248
  };
4005
4249
  function defaultHarmonicRhythm(ts) {
4006
- const bar2 = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, ts);
4250
+ const bar2 = _chunkS3QELJUEcjs.beatsPerBar.call(void 0, ts);
4007
4251
  const half = bar2 / 2;
4008
- return half % _chunkS5BKZZGMcjs.pulseBeats.call(void 0, ts) === 0 ? half : bar2;
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 _chunk3R3QVKY5cjs.isScaleTone.call(void 0, pitch, key) || cadencesThroughRaisedSeventh(key) && _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, pitch) === _chunk3R3QVKY5cjs.leadingTonePcOf.call(void 0, key);
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
- let best = _chunk3R3QVKY5cjs.majorKey.call(void 0, 0);
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(_chunk3R3QVKY5cjs.majorKey.call(void 0, tonic), _chunk3R3QVKY5cjs.minorKey.call(void 0, tonic));
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 = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc);
4272
+ const tonic = _chunkS3QELJUEcjs.pitchClassOf.call(void 0, key.rootPc);
4031
4273
  let score = 0;
4032
- for (const n of melody) {
4274
+ for (const n of line) {
4033
4275
  const w = Math.max(0.25, n.durationBeat);
4034
- const pc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, n.pitch);
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(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, note2.pitch))) {
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 || _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, closing.pitch) !== tonicPc) {
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 = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc);
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 + _chunkS5BKZZGMcjs.BEAT_EPS && end < last - _chunkS5BKZZGMcjs.BEAT_EPS) {
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))) > _chunkS5BKZZGMcjs.BEAT_EPS
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 - _chunkS5BKZZGMcjs.BEAT_EPS && span.startBeat >= start) {
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', _48 => _48[s], 'optionalAccess', _49 => _49.startBeat]), () => ( 0))) < end - _chunkS5BKZZGMcjs.BEAT_EPS) {
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, gridCount, "harmonic segments", budget);
4530
+ _chunkS3QELJUEcjs.assertGenerationBudget.call(void 0, gridCount, "harmonic segments", budget);
4283
4531
  const innerEnds = phraseEnds.filter(
4284
- (end) => end > segmentStart + _chunkS5BKZZGMcjs.BEAT_EPS && end < melodyEnd - _chunkS5BKZZGMcjs.BEAT_EPS
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, segCount, "harmonic segments", budget);
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, memberships, "note-to-segment memberships", budget);
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', _50 => _50[segment], 'optionalAccess', _51 => _51.noteIndices, 'access', _52 => _52.push, 'call', _53 => _53(index)]);
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', _54 => _54[idx], 'optionalAccess', _55 => _55.ornamental]) !== true || phraseClosingNotes.has(idx)
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: _chunkS5BKZZGMcjs.isStrongBeat.call(void 0, overlapStart, ts) });
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 = [0, 0.9, 0.3, 0.45, 0.45, 0.15, 0.9, 0.1, 0.3, 0.3, 0.3, 0.9];
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 UNSTABLE_QUALITIES = /* @__PURE__ */ new Set([
4348
- "dim",
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 = (_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, rootPc) - tonicPc + 12) % 12;
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
- _chunk3R3QVKY5cjs.tonicizableDegrees.call(void 0, key).map((degree) => [degree.degreeNumber, degree])
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(key, harmonic) {
4383
- const tonicPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc);
4384
- const frame = _chunk3R3QVKY5cjs.heptatonicFrameOf.call(void 0, key);
4385
- const tones = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, frame);
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 = _chunk3R3QVKY5cjs.diatonicTriad.call(void 0, degree, frame).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: _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, _chunk3R3QVKY5cjs.makeChord.call(void 0, rootPc, quality))
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: _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, _chunk3R3QVKY5cjs.makeChord.call(void 0, rootPc, "maj"))
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: _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, _chunk3R3QVKY5cjs.makeChord.call(void 0, rootPc, "dom7"))
4682
+ pcs: _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, _chunkYDGMWH43cjs.makeChord.call(void 0, rootPc, "dom7"))
4426
4683
  });
4427
4684
  }
4428
- const parallel = _chunkIFZDWIKMcjs.parallelKey.call(void 0, key);
4429
- const parallelTones = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, parallel);
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 = _chunk3R3QVKY5cjs.diatonicTriad.call(void 0, degree, parallel);
4433
- if (!_chunkIFZDWIKMcjs.isDiatonic.call(void 0, chord, key)) {
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(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc - tonicPc));
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: _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord)
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
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "harmonize options");
4474
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, opts.melody, "harmonize melody", {
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, end, "harmonize phrase end");
4737
+ _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, end, "harmonize phrase end");
4481
4738
  }
4482
- const soundingMelody = _chunkS5BKZZGMcjs.soundingNotesOnly.call(void 0, opts.melody);
4483
- const ts = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_METER)), "ts"));
4484
- _chunkS5BKZZGMcjs.assertTimeSignature.call(void 0, ts);
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 = _chunk3R3QVKY5cjs.resolveKey.call(void 0,
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 = _nullishCoalesce(opts.placement, () => ( DEFAULT_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 = _chunkS5BKZZGMcjs.assertOneOf.call(void 0,
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(key, harmonic);
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 = _chunkS5BKZZGMcjs.pulseBeats.call(void 0, ts);
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 = _chunkS5BKZZGMcjs.assertRange.call(void 0,
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0,
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 total = cost + keyFitCost(shifted, key) + tessituraCost(shifted);
4567
- if (total < bestCost) {
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', _56 => _56[s], 'optionalAccess', _57 => _57.startBeat]), () => ( segmentStart + s * hr))
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 = _chunk3R3QVKY5cjs.makeChord.call(void 0, cand.rootPc, cand.quality);
4594
- return { noteIndex, role: _chunkPM4XJE2Ycjs.roleOf.call(void 0, note2.pitch + bestTs, chord).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)) < _chunkS5BKZZGMcjs.BEAT_EPS;
4876
+ return Math.abs(bar2 - Math.round(bar2)) < _chunkS3QELJUEcjs.BEAT_EPS;
4614
4877
  }
4615
4878
  function nearestChordTone(pitch, chord) {
4616
- const pcs = _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord);
4879
+ const pcs = _chunkYDGMWH43cjs.chordPitchClasses.call(void 0, chord);
4617
4880
  for (let d = 0; d <= 12; d += 1) {
4618
- if (pcs.includes(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, pitch - d))) {
4881
+ if (pcs.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch - d))) {
4619
4882
  return pitch - d;
4620
4883
  }
4621
- if (pcs.includes(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, pitch + d))) {
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', _58 => _58.pitch]), () => ( 0));
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
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "motif options");
4702
- const contour = _nullishCoalesce(opts.contour, () => ( "arch"));
4703
- const bars = _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, opts.bars, "motif bars");
4704
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_TS4)), "ts")));
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, noteCount, "motif notes");
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 = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, opts.key);
4713
- const chord = opts.chord ? _chunk3R3QVKY5cjs.toChordData.call(void 0, opts.chord) : null;
4714
- const tonic = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, key.rootPc) + 60;
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 = _chunk3R3QVKY5cjs.shiftByScaleDegrees.call(void 0, tonic, (_nullishCoalesce(offsets[i], () => ( 0))) + jitter, key);
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: _chunkS5BKZZGMcjs.clampToMidi.call(void 0, pitch, "generated motif 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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, cell, "motif cell");
4740
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, read.notes, name);
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 : _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key));
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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
- _chunkS5BKZZGMcjs.assertOneOf.call(void 0, t, MOTIF_TRANSFORMS, "motif transform");
5028
+ _chunkS3QELJUEcjs.assertOneOf.call(void 0, t, MOTIF_TRANSFORMS, "motif transform");
4762
5029
  if (amount !== void 0) {
4763
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, amount, "motif transform amount");
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
- _chunkS5BKZZGMcjs.assertInteger.call(void 0,
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, _chunkS5BKZZGMcjs.InvalidInputError)("time transform amount must be positive");
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 ? _chunk3R3QVKY5cjs.shiftByScaleDegrees.call(void 0, n.pitch, degrees, key) : n.pitch + degrees
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 = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, ts, "ts"));
4837
- _chunkIFZDWIKMcjs.assertChordTimeline.call(void 0, timeline);
4838
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, bars, "development bars");
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 = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, key);
5107
+ const scale = _chunkYDGMWH43cjs.toKeyScale.call(void 0, key);
4841
5108
  const span = cellSpan(cell);
4842
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, meter);
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, tileCount * cellNotes.length, "developed motif notes");
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 cellNotes) {
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 ? _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord) : null;
4864
- const allows = chordTones ? (candidate) => chordTones.includes(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, candidate)) : (candidate) => _chunk3R3QVKY5cjs.isScaleTone.call(void 0, candidate, scale);
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({ pitch, startBeat, durationBeat: n.durationBeat });
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 = _chunkS5BKZZGMcjs.metricWeight.call(void 0, beat, meters);
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, _chunkS5BKZZGMcjs.InvalidInputError)(`${name} must be a string; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, value)}`);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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, _chunkS5BKZZGMcjs.InvalidInputError)(`${name} must be present; received undefined`);
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 = _chunkS5BKZZGMcjs.assertArray.call(void 0, value, name);
5209
+ const shares = _chunkS3QELJUEcjs.assertArray.call(void 0, value, name);
4928
5210
  if (shares.length !== length) {
4929
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`${name} must have length ${length}; received ${shares.length}`);
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 = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, shares[index], `${name}[${index}]`);
5215
+ const share = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, shares[index], `${name}[${index}]`);
4934
5216
  if (share < 0) {
4935
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`${name}[${index}] must be at least 0; received ${share}`);
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, _chunkS5BKZZGMcjs.InvalidInputError)(`${name} must sum to 1; received ${sum}`);
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, name);
5227
+ const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
4946
5228
  try {
4947
- _chunk3R3QVKY5cjs.resolveKey.call(void 0, read);
5229
+ _chunkYDGMWH43cjs.resolveKey.call(void 0, read);
4948
5230
  } catch (error) {
4949
- if (error instanceof _chunkS5BKZZGMcjs.InvalidInputError) {
4950
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`${name} must be a valid key: ${error.message}`);
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, name);
5239
+ const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
4958
5240
  assertString(read.label, `${name}.label`);
4959
- const startBeat = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
4960
- const endBeat = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, name);
4966
- const startBeat = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
4967
- const endBeat = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.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) => _chunkS5BKZZGMcjs.assertInteger.call(void 0, v, n, 0, Math.max(sectionCount - 1, 0))
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) => _chunkS5BKZZGMcjs.assertOneOf.call(void 0, v, _chunkIFZDWIKMcjs.CADENCE_TYPES, n));
4975
- _chunkS5BKZZGMcjs.assertOneOf.call(void 0, read.shape, _chunkIFZDWIKMcjs.MELODIC_CONTOUR_SHAPES, `${name}.shape`);
4976
- _chunkS5BKZZGMcjs.assertRange.call(void 0, read.peakPosition, 0, 1, `${name}.peakPosition`);
4977
- const register = _chunkS5BKZZGMcjs.assertRecord.call(void 0,
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
- _chunkS5BKZZGMcjs.assertMidiPitch.call(void 0, register.low, `${name}.register.low`);
4982
- _chunkS5BKZZGMcjs.assertMidiPitch.call(void 0, register.high, `${name}.register.high`);
4983
- _chunkS5BKZZGMcjs.assertRange.call(void 0, register.mean, 0, 127, `${name}.register.mean`);
4984
- _chunkS5BKZZGMcjs.assertRange.call(void 0, read.onsetDensity, 0, Number.MAX_SAFE_INTEGER, `${name}.onsetDensity`);
4985
- const motifs = _chunkS5BKZZGMcjs.assertArray.call(void 0, read.motifs, `${name}.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
- _chunkS5BKZZGMcjs.assertInteger.call(void 0,
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, name);
4998
- const startBeat = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
4999
- const endBeat = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.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 = _chunkS5BKZZGMcjs.assertInteger.call(void 0, read.key, `${name}.key`, 0, Math.max(keys.length - 1, 0));
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
- _chunkIFZDWIKMcjs.romanToChord.call(void 0, roman, keys[keyIndex]);
5286
+ _chunkLQZQDBCDcjs.romanToChord.call(void 0, roman, keys[keyIndex]);
5005
5287
  } catch (error) {
5006
- if (error instanceof _chunkS5BKZZGMcjs.InvalidInputError) {
5007
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(
5008
- `${name}.roman must be readable by romanToChord; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, roman)}: ${error.message}`
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, name);
5017
- _chunkS5BKZZGMcjs.assertOneOf.call(void 0, read.kind, _chunkIFZDWIKMcjs.MOTIF_RELATION_KINDS, `${name}.kind`);
5018
- _chunkS5BKZZGMcjs.assertFlag.call(void 0, read.sequence, `${name}.sequence`);
5019
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.semitones, `${name}.semitones`);
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
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.degrees, `${name}.degrees`);
5303
+ _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.degrees, `${name}.degrees`);
5022
5304
  } else if (read.degrees !== void 0) {
5023
- _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.degrees, `${name}.degrees`);
5305
+ _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.degrees, `${name}.degrees`);
5024
5306
  }
5025
- const timeRatio = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.timeRatio, `${name}.timeRatio`);
5307
+ const timeRatio = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, read.timeRatio, `${name}.timeRatio`);
5026
5308
  if (timeRatio <= 0) {
5027
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`${name}.timeRatio must be positive; received ${timeRatio}`);
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, name);
5033
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, read.phrase, `${name}.phrase`, 0, Math.max(phraseCount - 1, 0));
5034
- const startBeat = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.startBeat, `${name}.startBeat`);
5035
- const endBeat = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, read.endBeat, `${name}.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
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, read.notes, `${name}.notes`);
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) => _chunkS5BKZZGMcjs.assertInteger.call(void 0, v, n, 0, Math.max(motifCount - 1, 0))
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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) => _chunkS5BKZZGMcjs.assertArray.call(void 0, 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, _chunkS5BKZZGMcjs.InvalidInputError)(`${name}.rhythm must be null for a derived statement`);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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 = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, rhythm[index], `${name}.rhythm[${index}]`);
5348
+ const gap = _chunkS3QELJUEcjs.assertFiniteNumber.call(void 0, rhythm[index], `${name}.rhythm[${index}]`);
5067
5349
  if (gap <= 0) {
5068
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`${name}.rhythm[${index}] must be positive; received ${gap}`);
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
5073
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, name);
5363
+ const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
5082
5364
  assertMassDistribution(read.onsetLevels, 6, `${name}.onsetLevels`);
5083
- assertMassDistribution(read.interOnsetShares, _chunkIFZDWIKMcjs.RHYTHM_IOI_BINS.length, `${name}.interOnsetShares`);
5084
- _chunkS5BKZZGMcjs.assertRange.call(void 0, read.syncopation, 0, 1, `${name}.syncopation`);
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, name);
5370
+ const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, value, name);
5089
5371
  if (read.planVersion !== COMPOSITION_PLAN_VERSION) {
5090
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(
5091
- `${name}.planVersion must be ${COMPOSITION_PLAN_VERSION}; received ${_chunkS5BKZZGMcjs.describeRejected.call(void 0, read.planVersion)}`
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
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, read.seed, `${name}.seed`, 0, 4294967295);
5095
- _chunkS5BKZZGMcjs.assertInteger.call(void 0,
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
- _chunkCGBADIO5cjs.MIN_ALGORITHM_VERSION,
5099
- _chunkCGBADIO5cjs.ALGORITHM_VERSION
5380
+ _chunkWOMCXN2Wcjs.MIN_ALGORITHM_VERSION,
5381
+ _chunkWOMCXN2Wcjs.ALGORITHM_VERSION
5100
5382
  );
5101
- const keys = _chunkS5BKZZGMcjs.assertArray.call(void 0, read.keys, `${name}.keys`);
5383
+ const keys = _chunkS3QELJUEcjs.assertArray.call(void 0, read.keys, `${name}.keys`);
5102
5384
  if (keys.length === 0) {
5103
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(`${name}.keys must hold at least one key; received an empty array`);
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
- _chunkS5BKZZGMcjs.assertMeterMap.call(void 0, read.meters, `${name}.meters`);
5109
- const span = _chunkS5BKZZGMcjs.assertRecord.call(void 0,
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 = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, span.startBeat, `${name}.span.startBeat`);
5114
- const spanEnd = _chunkS5BKZZGMcjs.assertFiniteNumber.call(void 0, span.endBeat, `${name}.span.endBeat`);
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
- _chunkS5BKZZGMcjs.assertRange.call(void 0, span.bars, 0, Number.MAX_SAFE_INTEGER, `${name}.span.bars`);
5117
- const sections = _chunkS5BKZZGMcjs.assertArray.call(void 0, read.sections, `${name}.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 = _chunkS5BKZZGMcjs.assertArray.call(void 0, read.phrases, `${name}.phrases`);
5122
- const motifs = _chunkS5BKZZGMcjs.assertArray.call(void 0, read.motifs, `${name}.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 = _chunkS5BKZZGMcjs.assertArray.call(void 0, read.harmony, `${name}.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 _chunk3R3QVKY5cjs.spanFromChord.call(void 0, _chunkIFZDWIKMcjs.romanToChord.call(void 0, chord.roman, key), chord.startBeat);
5437
+ return _chunkYDGMWH43cjs.spanFromChord.call(void 0, _chunkLQZQDBCDcjs.romanToChord.call(void 0, chord.roman, key), chord.startBeat);
5156
5438
  });
5157
- return _chunkIFZDWIKMcjs.chordTimelineFromChords.call(void 0, spans, plan.span.endBeat);
5439
+ return _chunkLQZQDBCDcjs.chordTimelineFromChords.call(void 0, spans, plan.span.endBeat);
5158
5440
  }
5159
5441
 
5160
5442
  // src/generate/plan/harmony.ts
5161
- var HARMONY_OK_KINDS = /* @__PURE__ */ new Set([
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 _chunkIFZDWIKMcjs.keyLookup.call(void 0, regions, plan.keys[0]);
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 : _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, chord);
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 tones = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, _chunk3R3QVKY5cjs.scaleOf.call(void 0, plan.keys[_nullishCoalesce(_optionalChain([entry, 'optionalAccess', _59 => _59.key]), () => ( 0))]));
5193
- return CADENCE_DEGREES[cadence].map((degree) => tones[degree - 1]).filter((pc) => pc !== void 0);
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) => _chunk3R3QVKY5cjs.scaleOf.call(void 0, keyAt(beat));
5485
+ const scaleAt2 = (beat) => _chunkYDGMWH43cjs.scaleOf.call(void 0, keyAt(beat));
5198
5486
  return (line) => {
5199
- const analyzed = _chunkIFZDWIKMcjs.analyzeVoice.call(void 0, line, timeline.at, scaleAt2);
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', _60 => _60[index], 'optionalAccess', _61 => _61.labels]), () => ( []))).map((label) => label.kind);
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
- return position === "weak" && _chunk3R3QVKY5cjs.isScaleTone.call(void 0, note2.pitch, scaleAt2(note2.startBeat)) ? null : kinds;
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 && _chunk3R3QVKY5cjs.isForbiddenMelodicLeap.call(void 0, from, to)) {
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 = _chunkS5BKZZGMcjs.allocateCandidateTable.call(void 0,
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 = _chunkS5BKZZGMcjs.allocateCandidateTable.call(void 0,
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 = _chunkS5BKZZGMcjs.allocateChoiceTable.call(void 0,
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 transformMotif(transformMotif(cell, "invert"), "retrograde");
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" ? _chunk3R3QVKY5cjs.shiftByScaleDegrees.call(void 0, n.pitch, level, key) : n.pitch + shift,
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 - _chunkS5BKZZGMcjs.BEAT_EPS).map((n) => ({ ...n, durationBeat: Math.min(n.durationBeat, endBeat - n.startBeat) }));
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, _chunkS5BKZZGMcjs.NoSolutionError)(
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, _chunkS5BKZZGMcjs.NoSolutionError)(`no variation line fits the register ${frame.low}..${frame.high}`, {
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, input, "ctx");
5797
+ const read = _chunkS3QELJUEcjs.assertRecord.call(void 0, input, "ctx");
5506
5798
  if (read.rng !== void 0) {
5507
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)(
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', _62 => _62(scene.plan, beat), 'optionalAccess', _63 => _63.key]), () => ( 0))];
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 ? _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, 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(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, pitch))) : register.filter((pitch) => _chunk3R3QVKY5cjs.isScaleTone.call(void 0, pitch, scale));
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, _chunkS5BKZZGMcjs.NoSolutionError)(
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 && !_chunk3R3QVKY5cjs.isScaleTone.call(void 0, pitch, scale)) {
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', _64 => _64.motifs, 'access', _65 => _65[a], 'optionalAccess', _66 => _66.startBeat]), () => ( 0))) - (_nullishCoalesce(_optionalChain([plan, 'access', _67 => _67.motifs, 'access', _68 => _68[b], 'optionalAccess', _69 => _69.startBeat]), () => ( 0))) || a - b
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 + _chunkS5BKZZGMcjs.BEAT_EPS) {
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 + _chunkS5BKZZGMcjs.BEAT_EPS) {
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 = _chunkS5BKZZGMcjs.barStartBeat.call(void 0, startBeat, meters);
5620
- while (bar2 < endBeat - _chunkS5BKZZGMcjs.BEAT_EPS) {
5621
- const barEnd = bar2 + _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, bar2, meters);
5622
- for (let k = 0; bar2 + k / RHYTHM_SUBDIVISION < barEnd - _chunkS5BKZZGMcjs.BEAT_EPS; k += 1) {
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 + _chunkS5BKZZGMcjs.BEAT_EPS && beat < endBeat - _chunkS5BKZZGMcjs.BEAT_EPS) {
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, slots.length * Math.max(1, count - 1), "melody onset slots", scene.budget);
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, _chunkS5BKZZGMcjs.NoSolutionError)(
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) => _chunkIFZDWIKMcjs.rhythmLevel.call(void 0, beat, scene.plan.meters));
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[_chunkIFZDWIKMcjs.ioiBinIndex.call(void 0, slots[j] - slots[current])], () => ( 0));
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, _chunkS5BKZZGMcjs.NoSolutionError)(`no pitch line fits the register ${frame.low}..${frame.high}`, {
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 <= _chunkS5BKZZGMcjs.BEAT_EPS) {
5711
- throw new (0, _chunkS5BKZZGMcjs.NoSolutionError)(`root motif ${m} spans no time to place its notes in`, {
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 = _chunkIFZDWIKMcjs.barSpanOf.call(void 0, segment.startBeat, segment.endBeat, scene.plan.meters);
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 + _chunkS5BKZZGMcjs.BEAT_EPS) {
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 + _chunkS5BKZZGMcjs.BEAT_EPS && note2.startBeat + note2.durationBeat > downbeat + _chunkS5BKZZGMcjs.BEAT_EPS
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 - _chunkS5BKZZGMcjs.BEAT_EPS && note2.startBeat < phrase.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS
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(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, pitch))
6091
+ (pitch) => allowed.includes(_chunkS3QELJUEcjs.pitchClassOf.call(void 0, pitch))
5808
6092
  );
5809
6093
  if (candidates.length === 0) {
5810
- throw new (0, _chunkS5BKZZGMcjs.NoSolutionError)(
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(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, note2.pitch))) {
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, _chunkS5BKZZGMcjs.NoSolutionError)(`no cadence pitch joins its neighbours without an augmented step`, {
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 - _chunkS5BKZZGMcjs.BEAT_EPS && note2.startBeat < motif.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS
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, _chunkS5BKZZGMcjs.NoSolutionError)(`no pitch at the final downbeat joins its neighbours`, {
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, estimate, "melody pitch search", scene.budget);
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 = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
6168
+ const asked = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "opts");
5885
6169
  if (asked.budget !== void 0) {
5886
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, asked.budget, "budget", Number.MAX_SAFE_INTEGER);
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) => _chunk3R3QVKY5cjs.scaleOf.call(void 0, 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(scene, index);
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
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, ts) {
5944
- const strong = _chunkS5BKZZGMcjs.isStrongBeat.call(void 0, note2.startBeat, ts);
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 && _chunkS5BKZZGMcjs.isStrongBeat.call(void 0, next.startBeat, ts);
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 = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
5978
- _chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, notes, "ornament notes", { allowNonPositiveDuration: true });
5979
- const style = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, _nullishCoalesce(asked.style, () => ( DEFAULT_STYLE2)), ORNAMENT_STYLES, "ornament style");
5980
- const ts = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, _nullishCoalesce(asked.ts, () => ( DEFAULT_TS5)), "ts"));
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
- _chunkS5BKZZGMcjs.assertRange.call(void 0, asked.amount, 0, 1, "ornament amount");
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 = _chunkS5BKZZGMcjs.dropSilentNotes.call(void 0, notes);
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), ts)) {
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 ? {} : _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, "opts.preserve");
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 : _chunkS5BKZZGMcjs.assertRange.call(void 0, weight, 0, 1, `opts.preserve.${aspect}`);
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 = _chunkS5BKZZGMcjs.assertRecord.call(void 0, value, "opts.register");
6094
- const low = _chunkS5BKZZGMcjs.assertMidiPitch.call(void 0, read.low, "opts.register.low");
6095
- const high = _chunkS5BKZZGMcjs.assertMidiPitch.call(void 0, read.high, "opts.register.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, _chunkS5BKZZGMcjs.InvalidInputError)(
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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
- ({ key }) => ({
6113
- scale: { ...key.scale },
6114
- tonic: { ...key.tonic },
6115
- variant: key.variant
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 = _chunk3R3QVKY5cjs.resolveKey.call(void 0, requested);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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 = _chunkS5BKZZGMcjs.spelledInterval.call(void 0,
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: _chunkS5BKZZGMcjs.transposeByInterval.call(void 0, { letter: key.tonic.letter, alter: key.tonic.alter }, step),
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 > _chunkS5BKZZGMcjs.BEAT_EPS) {
6454
+ if (endBeat - startBeat > _chunkS3QELJUEcjs.BEAT_EPS) {
6171
6455
  planned.push({
6172
- label: keep ? section.label : _nullishCoalesce(_optionalChain([sections, 'access', _70 => _70[neighbour], 'optionalAccess', _71 => _71.label]), () => ( section.label)),
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 > _chunkS5BKZZGMcjs.BEAT_EPS) {
6467
+ while (left > _chunkS3QELJUEcjs.BEAT_EPS) {
6184
6468
  const step = Math.min(1, left);
6185
- beat += step * _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, beat, meters);
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 - _chunkS5BKZZGMcjs.BEAT_EPS) {
6194
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBarAt.call(void 0, beat, meters);
6195
- const step = Math.min(_chunkS5BKZZGMcjs.barStartBeat.call(void 0, beat, meters) + barBeats, endBeat) - beat;
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 + _chunkS5BKZZGMcjs.BEAT_EPS && beat < endBeat - _chunkS5BKZZGMcjs.BEAT_EPS) cuts.push(beat);
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 > _chunkS5BKZZGMcjs.BEAT_EPS) segments.push([from, to]);
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', _72 => _72.cadence, 'optionalAccess', _73 => _73.type]), () => ( null))
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 - _chunkS5BKZZGMcjs.BEAT_EPS && piece.startBeat < segmentEnd - _chunkS5BKZZGMcjs.BEAT_EPS
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 + _chunkS5BKZZGMcjs.BEAT_EPS;
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 - _chunkS5BKZZGMcjs.BEAT_EPS) return;
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', _74 => _74.at, 'call', _75 => _75(-1), 'optionalAccess', _76 => _76.source]), () => ( (profile.form.phrases.length > 0 ? 0 : -1))),
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 - _chunkS5BKZZGMcjs.BEAT_EPS && beat < section.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS
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 - _chunkS5BKZZGMcjs.BEAT_EPS && endBeat <= phrase.endBeat + _chunkS5BKZZGMcjs.BEAT_EPS
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 - _chunkS5BKZZGMcjs.BEAT_EPS) low = mid + 1;
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
- _chunkS5BKZZGMcjs.metricWeight.call(void 0, candidate.startBeat, meters) < STRONG_WEIGHT2 ? -1 : 0,
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) <= _chunkS5BKZZGMcjs.BEAT_EPS);
6345
- semitones += _nullishCoalesce(_optionalChain([relation, 'optionalAccess', _77 => _77.semitones]), () => ( 0));
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', _78 => _78.nodes, 'access', _79 => _79[node], 'optionalAccess', _80 => _80.startBeat]), () => ( 0))) - (_nullishCoalesce(_optionalChain([graph, 'access', _81 => _81.nodes, 'access', _82 => _82[edge.from], 'optionalAccess', _83 => _83.endBeat]), () => ( 0)));
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 >= -_chunkIFZDWIKMcjs.HUMANIZE_ADJACENCY && gap <= _chunkIFZDWIKMcjs.HUMANIZE_ADJACENCY,
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 (_chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, key).length !== HEPTATONIC_DEGREES) {
6663
+ if (_chunkYDGMWH43cjs.scaleTonesInDegreeOrder.call(void 0, key).length !== HEPTATONIC_DEGREES) {
6369
6664
  return null;
6370
6665
  }
6371
- return FUNCTION_DEGREES[fn].map((degree) => _chunkIFZDWIKMcjs.chordToRoman.call(void 0, _chunk3R3QVKY5cjs.diatonicTriad.call(void 0, degree, key), key));
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 : _chunkS5BKZZGMcjs.barStartBeat.call(void 0, chord.startBeat, profile.meters);
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) <= _chunkS5BKZZGMcjs.BEAT_EPS ? nextStart : Math.min(chord.endBeat, nextStart);
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 > _chunkS5BKZZGMcjs.BEAT_EPS) {
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 = _chunkIFZDWIKMcjs.assertReferenceProfile.call(void 0, reference, "reference");
6419
- const asked = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
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, _chunkS5BKZZGMcjs.InvalidInputError)("reference must carry melody onsets to derive a plan from");
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', _84 => _84.harmony, 'access', _85 => _85.keys, 'access', _86 => _86[0], 'optionalAccess', _87 => _87.key, 'access', _88 => _88.scale, 'access', _89 => _89.rootPc]), () => ( 0)))
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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', _90 => _90.form, 'access', _91 => _91.phrases, 'access', _92 => _92[span.source], 'optionalAccess', _93 => _93.melody]), () => ( null));
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', _94 => _94.melody, 'access', _95 => _95.motifs, 'access', _96 => _96[_nullishCoalesce(_optionalChain([graph, 'access', _97 => _97.nodes, 'access', _98 => _98[node], 'optionalAccess', _99 => _99.motif]), () => ( -1))], 'optionalAccess', _100 => _100.intervals, 'access', _101 => _101.length]), () => ( 0))) + 1;
6473
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, graph.nodes.length * phrases.length, "plan motif selection", asked.budget);
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', _102 => _102.nodes, 'access', _103 => _103[candidate.node], 'optionalAccess', _104 => _104.motif]), () => ( -1))];
6495
- _optionalChain([phrases, 'access', _105 => _105[candidate.phrase], 'optionalAccess', _106 => _106.motifs, 'access', _107 => _107.push, 'call', _108 => _108(index)]);
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 + _chunkS5BKZZGMcjs.BEAT_EPS && beat < plan.span.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS) {
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 + _chunkS5BKZZGMcjs.BEAT_EPS) {
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 + _chunkS5BKZZGMcjs.BEAT_EPS) {
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 = _chunkS5BKZZGMcjs.pulseBeats.call(void 0, _chunkS5BKZZGMcjs.meterAt.call(void 0, beat, plan.meters));
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 - _chunkS5BKZZGMcjs.BEAT_EPS && Math.abs(note2.startBeat + note2.durationBeat - beat) <= pulse2 + _chunkS5BKZZGMcjs.BEAT_EPS
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 - _chunkS5BKZZGMcjs.BEAT_EPS && rest.startBeat <= beat + pulse2 + _chunkS5BKZZGMcjs.BEAT_EPS && rest.endBeat >= beat - pulse2 - _chunkS5BKZZGMcjs.BEAT_EPS
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 + _chunkS5BKZZGMcjs.BEAT_EPS) {
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 - _chunkS5BKZZGMcjs.BEAT_EPS && note2.startBeat < phrase.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS ? [index] : []
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', _109 => _109[index], 'optionalAccess', _110 => _110.at, 'call', _111 => _111(-1)]);
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(_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, note2.pitch)))) {
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 - _chunkS5BKZZGMcjs.BEAT_EPS && note2.startBeat < motif.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS
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 - _chunkS5BKZZGMcjs.BEAT_EPS && note2.startBeat < endBeat - _chunkS5BKZZGMcjs.BEAT_EPS
6952
+ (note2) => note2.startBeat >= startBeat - _chunkS3QELJUEcjs.BEAT_EPS && note2.startBeat < endBeat - _chunkS3QELJUEcjs.BEAT_EPS
6652
6953
  );
6653
6954
  }
6654
- function replayLevel(source, derived, statement, sourceEnd, plan, key, closing) {
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
- statement.endBeat
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
- if (expected.length !== derived.length) {
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 = derived[i];
6996
+ const got = compared[i];
6686
6997
  if (i > 0) {
6687
- const gap = got.startBeat - derived[i - 1].startBeat;
6688
- holds = Math.abs(gap - (want.startBeat - expected[i - 1].startBeat)) <= _chunkS5BKZZGMcjs.BEAT_EPS;
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 similarity = _chunkIFZDWIKMcjs.melodicSimilarity.call(void 0, sourceNotes, derivedNotes);
6731
- if (similarity < _chunkIFZDWIKMcjs.DEFAULT_VARIATION_THRESHOLD) {
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 >= ${_chunkIFZDWIKMcjs.DEFAULT_VARIATION_THRESHOLD})`,
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
- sourceNotes,
6745
- derivedNotes,
7074
+ kept,
7075
+ notesInRange(melody, statement.startBeat, derivedKept),
6746
7076
  statement,
6747
- source.endBeat,
7077
+ sourceKept,
7078
+ derivedKept,
7079
+ sourceCut,
6748
7080
  plan,
6749
- _chunk3R3QVKY5cjs.scaleOf.call(void 0, keyAt(statement.startBeat)),
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 - _chunkS5BKZZGMcjs.BEAT_EPS && beat < phrase.endBeat - _chunkS5BKZZGMcjs.BEAT_EPS
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 = _chunkIFZDWIKMcjs.barSpanOf.call(void 0, phrase.startBeat, phrase.endBeat, plan.meters);
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 } = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "evaluate options");
7219
+ const { budget } = _chunkS3QELJUEcjs.assertOptions.call(void 0, opts, "evaluate options");
6888
7220
  const notes = [
6889
- ..._chunkS5BKZZGMcjs.assertNoteEvents.call(void 0, melody, "evaluated melody", { budget, allowNonPositiveDuration: true })
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) => _chunkIFZDWIKMcjs.phraseMelody.call(void 0, notes, phrase.startBeat, phrase.endBeat, _nullishCoalesce(lineMean, () => ( 0)), plan.meters, budget)
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 = _chunkIFZDWIKMcjs.analyzeRhythm.call(void 0, notes, {
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: _chunkIFZDWIKMcjs.contourSimilarity.call(void 0, plan.phrases.map(planContourPhrase), readings),
6919
- register: _chunkIFZDWIKMcjs.registerSimilarity.call(void 0, planRegisterPlan(plan), { phrases: readings, mean: lineMean }),
6920
- onset: _chunkIFZDWIKMcjs.onsetSimilarity.call(void 0, target, rhythm),
6921
- duration: _chunkIFZDWIKMcjs.durationSimilarity.call(void 0, target, rhythm),
6922
- syncopation: _chunkIFZDWIKMcjs.syncopationSimilarity.call(void 0, target, rhythm),
6923
- density: _chunkIFZDWIKMcjs.densitySimilarity.call(void 0, planDensity(plan), rhythm)
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 = _chunkS5BKZZGMcjs.assertOneOf.call(void 0, style, PROG_STYLES, "style");
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 = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, _chunk3R3QVKY5cjs.heptatonicFrameOf.call(void 0, key));
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 && _chunkIFZDWIKMcjs.isMinorKey.call(void 0, key) && degree === 5) {
7459
+ if (harmonicDominant && _chunkYDGMWH43cjs.cadencesThroughRaisedSeventh.call(void 0, key) && degree === 5) {
7128
7460
  return "maj";
7129
7461
  }
7130
- return _chunk3R3QVKY5cjs.diatonicTriad.call(void 0, degree, _chunk3R3QVKY5cjs.heptatonicFrameOf.call(void 0, key)).quality;
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, _chunkS5BKZZGMcjs.InvalidInputError)(`Unknown progression style: ${style}`);
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(_chunk3R3QVKY5cjs.tonicizableDegrees.call(void 0, key).map((degree) => degree.rootPc));
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 _chunk3R3QVKY5cjs.fifthPcOf.call(void 0, _chunk3R3QVKY5cjs.makeChord.call(void 0, span.rootPc, span.quality)) === (span.rootPc + 7) % 12;
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
- _chunkS5BKZZGMcjs.assertRecord.call(void 0, opts, "progression options");
7175
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, opts.bars, "progression bars");
7176
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, opts.bars, "progression chords");
7177
- const key = _chunk3R3QVKY5cjs.toKeyScale.call(void 0, opts.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
- if (opts.preset.degrees.length === 0) {
7182
- throw new (0, _chunkS5BKZZGMcjs.InvalidInputError)("progression preset must name at least one degree");
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(opts.preset.id, () => ( "custom")),
7186
- name: _nullishCoalesce(opts.preset.name, () => ( "Custom")),
7187
- degrees: opts.preset.degrees.map((degree, index) => {
7188
- _chunkS5BKZZGMcjs.assertDegree.call(void 0, degree, `progression preset degrees[${index}]`);
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, _chunkS5BKZZGMcjs.InvalidInputError)(
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: _nullishCoalesce(opts.preset.functional, () => ( "loop")),
7198
- styles: _nullishCoalesce(opts.preset.styles, () => ( [opts.style]))
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, _chunkS5BKZZGMcjs.InvalidInputError)(`Unknown progression preset: ${opts.presetId}`);
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" : _chunkS5BKZZGMcjs.assertOneOf.call(void 0, opts.ext, ["auto", ..._chunk3R3QVKY5cjs.chordQualities.call(void 0, )], "progression extension");
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', _112 => _112.degrees]), () => ( [0])),
7551
+ _nullishCoalesce(_optionalChain([preset, 'optionalAccess', _109 => _109.degrees]), () => ( [0])),
7211
7552
  key,
7553
+ tonic,
7212
7554
  ext,
7213
- _optionalChain([preset, 'optionalAccess', _113 => _113.functional]) === "cadenceStrong"
7555
+ _optionalChain([preset, 'optionalAccess', _110 => _110.functional]) === "cadenceStrong"
7214
7556
  );
7215
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, _nullishCoalesce(opts.ts, () => ( DEFAULT_TS6)));
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', _114 => _114.rootPc]), () => ( 0)),
7221
- quality: _nullishCoalesce(_optionalChain([step, 'optionalAccess', _115 => _115.quality]), () => ( "maj")),
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', _116 => _116.degree]) !== void 0) {
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 === "dom7";
7245
- const isResolutionTarget = _optionalChain([chords, 'access', _117 => _117[i - 1], 'optionalAccess', _118 => _118.secondaryDominant]) === true;
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) => _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, 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 = _chunk3R3QVKY5cjs.scaleTonesInDegreeOrder.call(void 0, key).length;
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(_chunk3R3QVKY5cjs.diatonicTriad.call(void 0, degree, key));
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 _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, a.rootPc) === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, b.rootPc) && a.quality === b.quality;
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 = _chunkS5BKZZGMcjs.noteToPitchClass.call(void 0, root) === _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc) && Math.abs(root.alter) <= MAX_HINT_ALTER;
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 : _chunk3R3QVKY5cjs.spellPitchClass.call(void 0, chord.rootPc, tonic, key))
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(_chunk3R3QVKY5cjs.spellPitchClass.call(void 0, chord.bassPc, tonic, key));
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, _chunk3R3QVKY5cjs.spellPitchClass.call(void 0, chord.rootPc, tonic, key), tonic, key);
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 = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, dominant.rootPc + 6);
7317
- if (_chunk3R3QVKY5cjs.isScaleTone.call(void 0, substituteRootPc, key)) {
7318
- return _chunk3R3QVKY5cjs.spellPitchClass.call(void 0, substituteRootPc, tonic, key);
7319
- }
7320
- const resolution = _chunk3R3QVKY5cjs.spellPitchClass.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, dominant.rootPc + 5), tonic, key);
7321
- return _chunkS5BKZZGMcjs.transposeNote.call(void 0, resolution, 1);
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
- _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
7325
- const source = _chunk3R3QVKY5cjs.toChordData.call(void 0, chord);
7326
- const { scale, tonic } = _chunk3R3QVKY5cjs.resolveKey.call(void 0, key);
7327
- const originalTriad = _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, _chunk3R3QVKY5cjs.makeChord.call(void 0, source.rootPc, triadQualityOf(source)));
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 (_chunk3R3QVKY5cjs.soundsDominantSeventh.call(void 0, source)) {
7330
- const substitute = _chunk3R3QVKY5cjs.makeChord.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, source.rootPc + 6), "dom7");
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 = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, triad.rootPc - source.rootPc);
7338
- if (THIRD_OFFSETS.includes(offset) && commonToneCount(originalTriad, _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, triad)) === 2) {
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 = _chunkIFZDWIKMcjs.functionOf.call(void 0, source, scale);
7343
- const parallel = _chunkIFZDWIKMcjs.parallelKey.call(void 0, scale);
7344
- for (const triad of diatonicTriadsOf(parallel)) {
7345
- if (_chunkIFZDWIKMcjs.functionOf.call(void 0, triad, scale) === targetFunction && !_chunkIFZDWIKMcjs.isDiatonic.call(void 0, triad, scale)) {
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 = _chunk3R3QVKY5cjs.makeChord.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, source.rootPc + offset), quality);
7352
- if (commonToneCount(originalTriad, _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, mediant)) === 1 && !_chunkIFZDWIKMcjs.isDiatonic.call(void 0, mediant, scale)) {
7353
- candidates.push({ chord: spelledInKey(mediant, tonic, scale), type: "chromaticMediant" });
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', _119 => _119.melodyPcs, 'optionalAccess', _120 => _120.map, 'call', _121 => _121(_chunkS5BKZZGMcjs.pitchClassOf)]);
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 = `${_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, candidate.chord.rootPc)}:${candidate.chord.quality}`;
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(_chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, candidate.chord));
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: _chunkIFZDWIKMcjs.chordToRoman.call(void 0, candidate.chord, scale),
7379
- function: _chunkIFZDWIKMcjs.functionOf.call(void 0, candidate.chord, scale)
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 { scale, tonic } = _chunk3R3QVKY5cjs.resolveKey.call(void 0, key);
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 = `${_chunkS5BKZZGMcjs.pitchClassOf.call(void 0, chord.rootPc)}:${chord.quality}`;
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: _chunkIFZDWIKMcjs.chordToRoman.call(void 0, chord, scale),
7397
- source: _chunkIFZDWIKMcjs.borrowedSource.call(void 0, chord, scale)
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 = _chunkIFZDWIKMcjs.parallelKey.call(void 0, scale);
7401
- for (const triad of diatonicTriadsOf(parallel)) {
7402
- if (!_chunkIFZDWIKMcjs.isDiatonic.call(void 0, triad, scale) && _chunkIFZDWIKMcjs.borrowedSource.call(void 0, triad, scale) !== null) {
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 = _chunk3R3QVKY5cjs.makeChord.call(void 0, _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, scale.rootPc + 1), "maj");
7407
- if (!_chunkIFZDWIKMcjs.isDiatonic.call(void 0, neapolitan, scale)) {
7408
- add(spelledOnRoot(neapolitan, _chunkS5BKZZGMcjs.transposeNote.call(void 0, tonic, 1), tonic, scale));
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 = _chunk3R3QVKY5cjs.toChordData.call(void 0, chord);
7414
- const { scale, tonic } = _chunk3R3QVKY5cjs.resolveKey.call(void 0, key);
7415
- const tonicPc = _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, scale.rootPc);
7416
- const mirror = (p) => _chunkS5BKZZGMcjs.pitchClassOf.call(void 0, 2 * tonicPc + 7 - p);
7417
- const pcs = _chunk3R3QVKY5cjs.chordPitchClasses.call(void 0, source).map(mirror);
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 = _chunkIFZDWIKMcjs.detectChordBest.call(void 0, pitches);
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(_chunk3R3QVKY5cjs.makeChord.call(void 0, detected.rootPc, detected.quality), tonic, scale);
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(_chunk3R3QVKY5cjs.makeChord.call(void 0, mirror(source.rootPc), quality, bassPc), tonic, scale);
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
- _chunkS5BKZZGMcjs.assertMidiPitch.call(void 0, pitch, "pitch");
7435
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, velocity, "velocity", 0, 127);
7436
- return _chunkS5BKZZGMcjs.assertArray.call(void 0, events, "events").map((event) => ({
7437
- pitch,
7438
- startBeat: event.position,
7439
- durationBeat: event.duration,
7440
- velocity
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
- _chunkS5BKZZGMcjs.assertInteger.call(void 0, weight, "weight", 0, 3);
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 = _chunkS5BKZZGMcjs.assertOptions.call(void 0, opts, "opts");
7461
- const meter = _chunkS5BKZZGMcjs.meterAt.call(void 0, 0, _chunkS5BKZZGMcjs.toMeterData.call(void 0, ts, "ts"));
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
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, bars, "rhythm bars");
7467
- _chunkS5BKZZGMcjs.assertPositiveInt.call(void 0, subdivision, "rhythm subdivision");
7468
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, meter);
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
- _chunkS5BKZZGMcjs.assertGenerationBudget.call(void 0, slotCount, "rhythm grid slots");
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 = _chunkS5BKZZGMcjs.metricWeight.call(void 0, position, meter);
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
- _chunkS5BKZZGMcjs.assertArray.call(void 0, events, "events");
7505
- const barBeats = _chunkS5BKZZGMcjs.beatsPerBar.call(void 0, ts);
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', _122 => _122.position]), () => ( 0))) + (_nullishCoalesce(_optionalChain([last, 'optionalAccess', _123 => _123.duration]), () => ( 0)));
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
- 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.doubleTime = doubleTime; exports.syncopate = syncopate; exports.ornamentBy = ornamentBy; exports.deform = deform; 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;
7591
- //# sourceMappingURL=chunk-B2PW6EHN.cjs.map
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