@libraz/libcantus 1.2.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 (131) hide show
  1. package/NOTICE +63 -0
  2. package/README.md +7 -1
  3. package/README_ja.md +17 -11
  4. package/dist/analyze/index.cjs +31 -7
  5. package/dist/analyze/index.cjs.map +1 -1
  6. package/dist/analyze/index.d.cts +161 -13
  7. package/dist/analyze/index.d.ts +161 -13
  8. package/dist/analyze/index.js +37 -13
  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-HPVSH7SF.cjs → chunk-3MDOEFIQ.cjs} +618 -954
  14. package/dist/chunk-3MDOEFIQ.cjs.map +1 -0
  15. package/dist/{chunk-FBH75DAY.js → chunk-5MWRBYAT.js} +560 -159
  16. package/dist/chunk-5MWRBYAT.js.map +1 -0
  17. package/dist/{chunk-J7FHVZII.cjs → chunk-6TTBEON3.cjs} +3074 -740
  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-HWHGOVO6.cjs → chunk-E3QO3UET.cjs} +31 -23
  22. package/dist/chunk-E3QO3UET.cjs.map +1 -0
  23. package/dist/{chunk-H2KJHBW4.js → chunk-FJFULJZE.js} +2375 -191
  24. package/dist/chunk-FJFULJZE.js.map +1 -0
  25. package/dist/{chunk-Q6LFSAKV.js → chunk-FK3DGAIZ.js} +2657 -323
  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-DSMJRXCZ.cjs → chunk-HYSVSFNI.cjs} +931 -530
  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-LQZQDBCD.cjs +5513 -0
  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-HYJJ2V2I.js → chunk-UTE5A36R.js} +483 -819
  46. package/dist/chunk-UTE5A36R.js.map +1 -0
  47. package/dist/{chunk-NFJ4P6ZZ.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 +20 -8
  67. package/dist/generate/index.cjs.map +1 -1
  68. package/dist/generate/index.d.cts +105 -17
  69. package/dist/generate/index.d.ts +105 -17
  70. package/dist/generate/index.js +19 -7
  71. package/dist/{index-CL4b4gUQ.d.ts → index-5VJgKz_Q.d.cts} +6 -2
  72. package/dist/{index-B9QLziDe.d.cts → index-BLuDesVG.d.ts} +20 -13
  73. package/dist/{index-BHIUyjhZ.d.ts → index-BV6APVa6.d.cts} +20 -13
  74. package/dist/{index-BMweUlm5.d.cts → 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-BNSM-DSk.d.cts → index-DVInzCDS.d.cts} +533 -28
  80. package/dist/{index-9eoQs2C1.d.ts → index-Dg-SAfhz.d.ts} +6 -4
  81. package/dist/{index-BJgP97N1.d.ts → index-jgeug9EA.d.ts} +533 -28
  82. package/dist/{index-cHvbYgJI.d.cts → index-pQihL4z7.d.cts} +6 -4
  83. package/dist/index.cjs +49 -13
  84. package/dist/index.cjs.map +1 -1
  85. package/dist/index.d.cts +13 -13
  86. package/dist/index.d.ts +13 -13
  87. package/dist/index.js +55 -19
  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 +259 -48
  93. package/dist/model/index.d.ts +259 -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/{index-BRMbPkHE.d.ts → profile-B4WqcM4H.d.ts} +85 -610
  98. package/dist/{index-DGCNKAUr.d.cts → profile-BJd1XkPB.d.cts} +85 -610
  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/{index-CJBBiAmU.d.ts → types-7mGFwvMm.d.ts} +1210 -31
  105. package/dist/{index-BBWNZS0f.d.cts → types-_ofpb2be.d.cts} +1210 -31
  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-76ZBTRG2.cjs.map +0 -1
  110. package/dist/chunk-7KG3RTYS.js.map +0 -1
  111. package/dist/chunk-AGOVW7U6.js.map +0 -1
  112. package/dist/chunk-CGBADIO5.cjs.map +0 -1
  113. package/dist/chunk-DSMJRXCZ.cjs.map +0 -1
  114. package/dist/chunk-FBH75DAY.js.map +0 -1
  115. package/dist/chunk-H2KJHBW4.js.map +0 -1
  116. package/dist/chunk-HPVSH7SF.cjs.map +0 -1
  117. package/dist/chunk-HWHGOVO6.cjs.map +0 -1
  118. package/dist/chunk-HYJJ2V2I.js.map +0 -1
  119. package/dist/chunk-J7FHVZII.cjs.map +0 -1
  120. package/dist/chunk-M5RYMAFI.js.map +0 -1
  121. package/dist/chunk-NB25P3EH.js.map +0 -1
  122. package/dist/chunk-NFJ4P6ZZ.js.map +0 -1
  123. package/dist/chunk-NM7UAMC3.cjs.map +0 -1
  124. package/dist/chunk-PM4XJE2Y.cjs.map +0 -1
  125. package/dist/chunk-PUKJP2Z5.js.map +0 -1
  126. package/dist/chunk-Q6LFSAKV.js.map +0 -1
  127. package/dist/chunk-RFIBF2RR.js.map +0 -1
  128. package/dist/chunk-S5BKZZGM.cjs.map +0 -1
  129. package/dist/chunk-SGLEQVJH.cjs +0 -3329
  130. package/dist/chunk-SGLEQVJH.cjs.map +0 -1
  131. package/dist/chunk-UMWZ4ZET.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import {
2
- appliedDominantTarget,
2
+ appliedChordTarget,
3
3
  assertChord,
4
4
  chordPitchClasses,
5
5
  chordQualities,
6
+ chordSpecForQuality,
6
7
  chordToneRole,
7
8
  classifySpelledInterval,
8
9
  createsBattuta,
@@ -12,7 +13,6 @@ import {
12
13
  createsVoiceOverlap,
13
14
  exceedsSpacing,
14
15
  formatChordSymbol,
15
- hasDominantSonority,
16
16
  isAugmentedMelodicInterval,
17
17
  isDescendingStep,
18
18
  isForbiddenMelodicLeap,
@@ -22,6 +22,7 @@ import {
22
22
  isNeapolitanChordOf,
23
23
  leadingTonePcOf,
24
24
  makeChord,
25
+ makeSpelledChord,
25
26
  noteNames,
26
27
  resolveKey,
27
28
  scaleTonesInDegreeOrder,
@@ -33,7 +34,7 @@ import {
33
34
  spellScale,
34
35
  toChordData,
35
36
  toKeyScale
36
- } from "./chunk-RFIBF2RR.js";
37
+ } from "./chunk-H7FVMBUC.js";
37
38
  import {
38
39
  BEAT_EPS,
39
40
  InvalidInputError,
@@ -42,6 +43,7 @@ import {
42
43
  assertFiniteNumber,
43
44
  assertGenerationBudget,
44
45
  assertInteger,
46
+ assertOneOf,
45
47
  assertOptions,
46
48
  assertPositiveInt,
47
49
  describeRejected,
@@ -55,7 +57,7 @@ import {
55
57
  toNoteData,
56
58
  toSpelledInterval,
57
59
  transposeByInterval
58
- } from "./chunk-AGOVW7U6.js";
60
+ } from "./chunk-YYVXRV3V.js";
59
61
 
60
62
  // src/theory/transposition/index.ts
61
63
  var TRANSPOSING_INSTRUMENTS = Object.freeze({
@@ -146,8 +148,10 @@ var SINGLE_ACCIDENTALS = {
146
148
  n: "natural",
147
149
  "\u266E": "natural"
148
150
  };
149
- var FIGURE_SEPARATORS = /* @__PURE__ */ new Set([" ", " ", ",", "/"]);
150
- var MOTION_MARKS = /* @__PURE__ */ new Set(["-", "\u2013"]);
151
+ var FIGURE_SEPARATOR_LIST = [" ", " ", ",", "/"];
152
+ var FIGURE_SEPARATORS = new Set(FIGURE_SEPARATOR_LIST);
153
+ var MOTION_MARK_LIST = ["-", "\u2013"];
154
+ var MOTION_MARKS = new Set(MOTION_MARK_LIST);
151
155
  var PRINTED_ACCIDENTALS = [
152
156
  ["natural", "n", 0],
153
157
  ["sharp", "#", 1],
@@ -203,6 +207,16 @@ function readFigure(text, start) {
203
207
  }
204
208
  return { figure: { number: 3, accidental }, index };
205
209
  }
210
+ function readStack(text, start) {
211
+ const figures = [];
212
+ let index = start;
213
+ do {
214
+ const read = readFigure(text, index);
215
+ figures.push(read.figure);
216
+ index = read.index;
217
+ } while (index < text.length && !FIGURE_SEPARATORS.has(text[index] ?? "") && !MOTION_MARKS.has(text[index] ?? ""));
218
+ return { figures, index };
219
+ }
206
220
  function parseFigures(text) {
207
221
  const figures = [];
208
222
  const motions = [];
@@ -212,21 +226,30 @@ function parseFigures(text) {
212
226
  index += 1;
213
227
  continue;
214
228
  }
215
- const first = readFigure(text, index);
229
+ const first = readStack(text, index);
216
230
  index = first.index;
217
231
  if (!MOTION_MARKS.has(text[index] ?? "")) {
218
- figures.push(first.figure);
232
+ figures.push(...first.figures);
219
233
  continue;
220
234
  }
221
- const second = readFigure(text, index + 1);
235
+ const second = readStack(text, index + 1);
222
236
  index = second.index;
223
237
  if (MOTION_MARKS.has(text[index] ?? "")) {
224
238
  throw invalidFigures(text, "chains more than one motion onto a single figure");
225
239
  }
226
- if (first.figure.number === second.figure.number) {
227
- throw invalidFigures(text, `moves the interval ${first.figure.number} onto itself`);
240
+ if (first.figures.length !== second.figures.length) {
241
+ throw invalidFigures(
242
+ text,
243
+ `moves ${first.figures.length} run-together figures onto ${second.figures.length}`
244
+ );
228
245
  }
229
- motions.push({ from: first.figure, to: second.figure });
246
+ first.figures.forEach((from, column) => {
247
+ const to = second.figures[column];
248
+ if (from.number === to.number) {
249
+ throw invalidFigures(text, `moves the interval ${from.number} onto itself`);
250
+ }
251
+ motions.push({ from, to });
252
+ });
230
253
  }
231
254
  return { figures, motions };
232
255
  }
@@ -237,7 +260,7 @@ var SEVENTH = { intervals: [3, 5, 7], rootInterval: 1 };
237
260
  var SEVENTH_FIRST = { intervals: [3, 5, 6], rootInterval: 6 };
238
261
  var SEVENTH_SECOND = { intervals: [3, 4, 6], rootInterval: 4 };
239
262
  var SEVENTH_THIRD = { intervals: [2, 4, 6], rootInterval: 2 };
240
- var FIGURE_SETS = /* @__PURE__ */ new Map([
263
+ var FIGURE_SET_ENTRIES = [
241
264
  ["", TRIAD],
242
265
  ["3", TRIAD],
243
266
  ["5", TRIAD],
@@ -256,8 +279,9 @@ var FIGURE_SETS = /* @__PURE__ */ new Map([
256
279
  ["2", SEVENTH_THIRD],
257
280
  ["2,4", SEVENTH_THIRD],
258
281
  ["2,4,6", SEVENTH_THIRD]
259
- ]);
260
- var FIGURE_ABBREVIATIONS = /* @__PURE__ */ new Map([
282
+ ];
283
+ var FIGURE_SETS = new Map(FIGURE_SET_ENTRIES);
284
+ var FIGURE_ABBREVIATION_ENTRIES = [
261
285
  [TRIAD.intervals.join(","), []],
262
286
  [TRIAD_FIRST.intervals.join(","), [6]],
263
287
  [TRIAD_SECOND.intervals.join(","), [6, 4]],
@@ -265,13 +289,18 @@ var FIGURE_ABBREVIATIONS = /* @__PURE__ */ new Map([
265
289
  [SEVENTH_FIRST.intervals.join(","), [6, 5]],
266
290
  [SEVENTH_SECOND.intervals.join(","), [4, 3]],
267
291
  [SEVENTH_THIRD.intervals.join(","), [4, 2]]
268
- ]);
292
+ ];
293
+ var FIGURE_ABBREVIATIONS = new Map(
294
+ FIGURE_ABBREVIATION_ENTRIES
295
+ );
296
+ var TERTIAN_BASES = /* @__PURE__ */ new Set(["maj", "min", "dim", "aug"]);
269
297
  function tertianQualityIndex() {
270
298
  const index = /* @__PURE__ */ new Map();
271
299
  for (const quality of chordQualities()) {
272
300
  const { intervals } = makeChord(0, quality);
273
301
  const template = intervals.join(",");
274
- if (intervals.length >= 3 && intervals.length <= MAX_STACK_SIZE && !index.has(template)) {
302
+ const spec = chordSpecForQuality(quality, 0);
303
+ if (intervals.length >= 3 && intervals.length <= MAX_STACK_SIZE && TERTIAN_BASES.has(spec.base) && spec.additions.length === 0 && !index.has(template)) {
275
304
  index.set(template, quality);
276
305
  }
277
306
  }
@@ -325,9 +354,11 @@ function realizeSonority(bass, resolved, text, alters) {
325
354
  `figured bass ${describeRejected(text)} sounds ${noteNames(tones).join(" ")}, which no chord quality names`
326
355
  );
327
356
  }
328
- const chord = makeChord(rootPc, quality, noteToPitchClass(bass));
329
- chord.rootSpelling = { letter: root.letter, alter: root.alter };
330
- chord.bassSpelling = { letter: bass.letter, alter: bass.alter };
357
+ const chord = makeSpelledChord(rootPc, quality, {
358
+ bassPc: noteToPitchClass(bass),
359
+ rootSpelling: { letter: root.letter, alter: root.alter },
360
+ bassSpelling: { letter: bass.letter, alter: bass.alter }
361
+ });
331
362
  return { chord, notes };
332
363
  }
333
364
  function figuredBassRealization(bass, figures, key) {
@@ -416,11 +447,11 @@ function assertRealizesAs(bass, figures, key, tones) {
416
447
  }
417
448
 
418
449
  // src/theory/partwriting/cross-relation.ts
419
- function resolvesAsAppliedDominant(chord, next, key) {
420
- if (next === void 0 || !hasDominantSonority(chord)) {
450
+ function resolvesAsAppliedChord(chord, next, key) {
451
+ if (next === void 0) {
421
452
  return false;
422
453
  }
423
- const target = appliedDominantTarget(chord.rootPc + 5, key);
454
+ const target = appliedChordTarget(chord, key);
424
455
  return target !== null && pitchClassOf(next.rootPc) === target.rootPc;
425
456
  }
426
457
  function soundsAugmentedSixth(moment, key) {
@@ -437,7 +468,7 @@ function soundsAugmentedSixth(moment, key) {
437
468
  });
438
469
  }
439
470
  function isChromaticHarmony(moment, next, key) {
440
- return resolvesAsAppliedDominant(moment.chord, next, key) || isNeapolitanChordOf(moment.chord, key) || soundsAugmentedSixth(moment, key);
471
+ return resolvesAsAppliedChord(moment.chord, next, key) || isNeapolitanChordOf(moment.chord, key) || soundsAugmentedSixth(moment, key);
441
472
  }
442
473
  function approachedByStep(before, moment, voice) {
443
474
  const earlier = before?.[voice];
@@ -445,7 +476,8 @@ function approachedByStep(before, moment, voice) {
445
476
  if (earlier === void 0 || later === void 0) {
446
477
  return false;
447
478
  }
448
- return spelledInterval(earlier, later).number === 2;
479
+ const interval = spelledInterval(earlier, later);
480
+ return interval.number === 2 || interval.number === 1 && Math.abs(interval.semitones) === 1;
449
481
  }
450
482
  function isOuterVoice(voice, notes) {
451
483
  return voice === 0 || voice === notes.length - 1;
@@ -1116,7 +1148,11 @@ function nearestPc(target, pcs) {
1116
1148
  function voiceChordStyled(given, opts) {
1117
1149
  assertOptions(opts, "opts");
1118
1150
  const chord = toChordData(given);
1119
- const style = opts?.style ?? "close";
1151
+ const style = assertOneOf(
1152
+ opts?.style ?? "close",
1153
+ ["close", "drop2", "drop3", "shell", "rootless"],
1154
+ "styled voicing style"
1155
+ );
1120
1156
  const octave = opts?.octave ?? DEFAULT_STYLE_OCTAVE;
1121
1157
  assertInteger(octave, "styled voicing octave", -10, 10);
1122
1158
  if (opts?.topNote !== void 0) {
@@ -1739,6 +1775,10 @@ function cadenceViolations(entries, mode, counterpointAbove) {
1739
1775
  function resolveDurations(counterpoint, measures, species, opts) {
1740
1776
  const given = opts?.durations;
1741
1777
  if (given !== void 0) {
1778
+ assertArray(given, "durations");
1779
+ given.forEach((duration, index) => {
1780
+ assertFiniteNumber(duration, `durations[${index}]`);
1781
+ });
1742
1782
  if (given.length !== counterpoint.length) {
1743
1783
  return {
1744
1784
  problem: `The exercise gives ${given.length} durations for ${counterpoint.length} notes`
@@ -1860,9 +1900,9 @@ function checkSpecies(cantusFirmus, counterpoint, species, modeLike, opts) {
1860
1900
  }
1861
1901
  }
1862
1902
  violations.push(...melodicShapeViolations(struck, species));
1863
- for (const [from, to] of motionPairs(struck)) {
1864
- const previous = struck[from];
1865
- const current = struck[to];
1903
+ for (const [from, to] of motionPairs(entries)) {
1904
+ const previous = entries[from];
1905
+ const current = entries[to];
1866
1906
  if (previous !== void 0 && current !== void 0) {
1867
1907
  violations.push(...motionViolations(previous, current, counterpointAbove));
1868
1908
  }
@@ -1942,7 +1982,7 @@ function pairViolations(transition) {
1942
1982
  continue;
1943
1983
  }
1944
1984
  if (createsParallelPerfect(upperPrev, upperCur, lowerPrev, lowerCur)) {
1945
- const fifth = pitchClassOf(upperCur - lowerCur) === 7;
1985
+ const fifth = pitchClassOf(Math.abs(upperCur - lowerCur)) === 7;
1946
1986
  found.push(
1947
1987
  violation(
1948
1988
  fifth ? "parallelFifth" : "parallelOctave",
@@ -2135,4 +2175,4 @@ export {
2135
2175
  spellVoicing,
2136
2176
  checkPartWriting
2137
2177
  };
2138
- //# sourceMappingURL=chunk-M5RYMAFI.js.map
2178
+ //# sourceMappingURL=chunk-ZLNSH4UL.js.map