@libraz/libcantus 0.9.3 → 0.9.4

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 (198) hide show
  1. package/README.md +2 -2
  2. package/dist/analyze/index.cjs +39 -1947
  3. package/dist/analyze/index.cjs.map +1 -1
  4. package/dist/analyze/index.d.cts +197 -37
  5. package/dist/analyze/index.d.ts +197 -37
  6. package/dist/analyze/index.js +19 -8
  7. package/dist/chunk-36N73KZ3.cjs +246 -0
  8. package/dist/chunk-36N73KZ3.cjs.map +1 -0
  9. package/dist/chunk-4HLLZPXT.cjs +3077 -0
  10. package/dist/chunk-4HLLZPXT.cjs.map +1 -0
  11. package/dist/chunk-7MGZ7D62.cjs +498 -0
  12. package/dist/chunk-7MGZ7D62.cjs.map +1 -0
  13. package/dist/{chunk-4MHA432G.js → chunk-7NKDPF74.js} +403 -180
  14. package/dist/chunk-7NKDPF74.js.map +1 -0
  15. package/dist/chunk-CAN76NCU.cjs +679 -0
  16. package/dist/chunk-CAN76NCU.cjs.map +1 -0
  17. package/dist/{chunk-MIWO425M.js → chunk-D2FAJBYL.js} +101 -34
  18. package/dist/chunk-D2FAJBYL.js.map +1 -0
  19. package/dist/{chunk-SGU7SPLK.js → chunk-EHVEBWM5.js} +1056 -531
  20. package/dist/chunk-EHVEBWM5.js.map +1 -0
  21. package/dist/chunk-FCANXBAT.cjs +30 -0
  22. package/dist/chunk-FCANXBAT.cjs.map +1 -0
  23. package/dist/chunk-FNDWXRRI.cjs +479 -0
  24. package/dist/chunk-FNDWXRRI.cjs.map +1 -0
  25. package/dist/{chunk-IT2O4XFE.js → chunk-GQSGS2N4.js} +43 -24
  26. package/dist/chunk-GQSGS2N4.js.map +1 -0
  27. package/dist/{chunk-62QZKCJQ.js → chunk-HKGYCQ34.js} +10 -6
  28. package/dist/chunk-HKGYCQ34.js.map +1 -0
  29. package/dist/{chunk-AKLYPWIN.js → chunk-I24MV65U.js} +29 -6
  30. package/dist/chunk-I24MV65U.js.map +1 -0
  31. package/dist/{chunk-CHMXELDS.js → chunk-KMHOICIY.js} +311 -181
  32. package/dist/chunk-KMHOICIY.js.map +1 -0
  33. package/dist/chunk-LW53AHQU.cjs +1117 -0
  34. package/dist/chunk-LW53AHQU.cjs.map +1 -0
  35. package/dist/{chunk-2ZWMSJH6.js → chunk-NKIBQ6PT.js} +2 -2
  36. package/dist/chunk-NKIBQ6PT.js.map +1 -0
  37. package/dist/chunk-NP4NA2FB.cjs +106 -0
  38. package/dist/chunk-NP4NA2FB.cjs.map +1 -0
  39. package/dist/chunk-NVE34YGZ.cjs +1449 -0
  40. package/dist/chunk-NVE34YGZ.cjs.map +1 -0
  41. package/dist/{chunk-EH6EM37U.js → chunk-NYYWMV2C.js} +61 -49
  42. package/dist/chunk-NYYWMV2C.js.map +1 -0
  43. package/dist/{chunk-GOAW4VYL.js → chunk-Q2XUP227.js} +243 -117
  44. package/dist/chunk-Q2XUP227.js.map +1 -0
  45. package/dist/chunk-Q6OP4U43.cjs +327 -0
  46. package/dist/chunk-Q6OP4U43.cjs.map +1 -0
  47. package/dist/chunk-RC6GBMCD.cjs +845 -0
  48. package/dist/chunk-RC6GBMCD.cjs.map +1 -0
  49. package/dist/{chunk-C5XYKUVG.js → chunk-RK35RIN7.js} +370 -157
  50. package/dist/chunk-RK35RIN7.js.map +1 -0
  51. package/dist/chunk-RUMU3UA6.cjs +53 -0
  52. package/dist/chunk-RUMU3UA6.cjs.map +1 -0
  53. package/dist/chunk-T64C7ZD7.cjs +1 -0
  54. package/dist/chunk-T64C7ZD7.cjs.map +1 -0
  55. package/dist/chunk-XEBG3G53.js +498 -0
  56. package/dist/chunk-XEBG3G53.js.map +1 -0
  57. package/dist/{chunk-I5R7ZBJS.js → chunk-YLEMGEFH.js} +103 -59
  58. package/dist/chunk-YLEMGEFH.js.map +1 -0
  59. package/dist/chunk-ZEJR4TKL.cjs +173 -0
  60. package/dist/chunk-ZEJR4TKL.cjs.map +1 -0
  61. package/dist/core/index.cjs +130 -647
  62. package/dist/core/index.cjs.map +1 -1
  63. package/dist/core/index.d.cts +301 -39
  64. package/dist/core/index.d.ts +301 -39
  65. package/dist/core/index.js +54 -16
  66. package/dist/{function-DYt4iKsn.d.cts → function-BtiZb9i9.d.ts} +28 -7
  67. package/dist/{function-DVH4Eusr.d.ts → function-DNugAOrt.d.cts} +28 -7
  68. package/dist/generate/index.cjs +28 -4085
  69. package/dist/generate/index.cjs.map +1 -1
  70. package/dist/generate/index.d.cts +370 -62
  71. package/dist/generate/index.d.ts +370 -62
  72. package/dist/generate/index.js +23 -9
  73. package/dist/{index-CxqBQtH1.d.cts → index-6VR8-kit.d.ts} +19 -4
  74. package/dist/index-70p168VM.d.ts +192 -0
  75. package/dist/{index-CpOsP1y9.d.cts → index-Be74mcon.d.cts} +18 -17
  76. package/dist/index-BtXT6UQ0.d.cts +192 -0
  77. package/dist/{index-DxvARIP2.d.ts → index-C5UBbQ4G.d.ts} +18 -17
  78. package/dist/{index-Bt4tOUD9.d.ts → index-C83mZI1P.d.ts} +93 -8
  79. package/dist/{index-Bg5dYMmZ.d.ts → index-D6b6na69.d.cts} +14 -11
  80. package/dist/{index-Cl7mhOFM.d.cts → index-DXd9JikN.d.cts} +92 -10
  81. package/dist/{index-Cl7mhOFM.d.ts → index-DXd9JikN.d.ts} +92 -10
  82. package/dist/index-OG65ocOr.d.cts +272 -0
  83. package/dist/index-OG65ocOr.d.ts +272 -0
  84. package/dist/{index-Jc0Ryi79.d.ts → index-tJhkmQgE.d.cts} +19 -4
  85. package/dist/{index-Dikst44v.d.cts → index-tSQh-xwY.d.ts} +14 -11
  86. package/dist/{index-BNlGP86A.d.cts → index-y_ak9_Hi.d.cts} +93 -8
  87. package/dist/index.cjs +419 -7383
  88. package/dist/index.cjs.map +1 -1
  89. package/dist/index.d.cts +14 -14
  90. package/dist/index.d.ts +14 -14
  91. package/dist/index.js +111 -27
  92. package/dist/model/index.cjs +8 -2562
  93. package/dist/model/index.cjs.map +1 -1
  94. package/dist/model/index.d.cts +433 -75
  95. package/dist/model/index.d.ts +433 -75
  96. package/dist/model/index.js +6 -7
  97. package/dist/styled-DIRkk9Uz.d.ts +506 -0
  98. package/dist/styled-DJbkJQfj.d.cts +506 -0
  99. package/dist/theory/index.cjs +172 -1822
  100. package/dist/theory/index.cjs.map +1 -1
  101. package/dist/theory/index.d.cts +151 -233
  102. package/dist/theory/index.d.ts +151 -233
  103. package/dist/theory/index.js +30 -7
  104. package/dist/{types-MGP29r3t.d.cts → types-BN6_Q9Kl.d.cts} +11 -2
  105. package/dist/{types-MGP29r3t.d.ts → types-BN6_Q9Kl.d.ts} +11 -2
  106. package/package.json +24 -6
  107. package/dist/chunk-2ZWMSJH6.js.map +0 -1
  108. package/dist/chunk-4MHA432G.js.map +0 -1
  109. package/dist/chunk-62QZKCJQ.js.map +0 -1
  110. package/dist/chunk-AKLYPWIN.js.map +0 -1
  111. package/dist/chunk-C5XYKUVG.js.map +0 -1
  112. package/dist/chunk-CHMXELDS.js.map +0 -1
  113. package/dist/chunk-DYWFNC4A.js +0 -152
  114. package/dist/chunk-DYWFNC4A.js.map +0 -1
  115. package/dist/chunk-EH6EM37U.js.map +0 -1
  116. package/dist/chunk-FBQK3ZQN.js +0 -131
  117. package/dist/chunk-FBQK3ZQN.js.map +0 -1
  118. package/dist/chunk-GOAW4VYL.js.map +0 -1
  119. package/dist/chunk-I5R7ZBJS.js.map +0 -1
  120. package/dist/chunk-IT2O4XFE.js.map +0 -1
  121. package/dist/chunk-MIWO425M.js.map +0 -1
  122. package/dist/chunk-SGU7SPLK.js.map +0 -1
  123. package/dist/index-CGMZNCx6.d.cts +0 -140
  124. package/dist/index-CGMZNCx6.d.ts +0 -140
  125. package/dist/index-CnZCo29u.d.cts +0 -108
  126. package/dist/index-JnF4v9bx.d.ts +0 -108
  127. package/dist/styled-DZ7GjShb.d.ts +0 -282
  128. package/dist/styled-ZTbdaVFM.d.cts +0 -282
  129. package/src/analyze/arrange/index.ts +0 -21
  130. package/src/analyze/arrange/internal.ts +0 -127
  131. package/src/analyze/arrange/tension.ts +0 -199
  132. package/src/analyze/arrange/tracks.ts +0 -312
  133. package/src/analyze/detect/index.ts +0 -272
  134. package/src/analyze/functional/borrowed.ts +0 -84
  135. package/src/analyze/functional/cadence.ts +0 -66
  136. package/src/analyze/functional/function.ts +0 -184
  137. package/src/analyze/functional/index.ts +0 -23
  138. package/src/analyze/functional/internal.ts +0 -29
  139. package/src/analyze/functional/roman.ts +0 -402
  140. package/src/analyze/index.ts +0 -49
  141. package/src/analyze/timeline/index.ts +0 -451
  142. package/src/analyze/voice/index.ts +0 -339
  143. package/src/core/event-index/index.ts +0 -104
  144. package/src/core/index.ts +0 -61
  145. package/src/core/interval/index.ts +0 -81
  146. package/src/core/meter/index.ts +0 -302
  147. package/src/core/pitch/index.ts +0 -311
  148. package/src/core/random/index.ts +0 -76
  149. package/src/core/tuning/index.ts +0 -186
  150. package/src/core/types.ts +0 -29
  151. package/src/core/validation/index.ts +0 -119
  152. package/src/generate/bass/index.ts +0 -373
  153. package/src/generate/countermelody/index.ts +0 -470
  154. package/src/generate/drums/beat.ts +0 -266
  155. package/src/generate/drums/euclid.ts +0 -65
  156. package/src/generate/drums/fills.ts +0 -356
  157. package/src/generate/drums/ghost.ts +0 -119
  158. package/src/generate/drums/hihat.ts +0 -285
  159. package/src/generate/drums/hit.ts +0 -31
  160. package/src/generate/drums/index.ts +0 -361
  161. package/src/generate/drums/internal.ts +0 -257
  162. package/src/generate/drums/kick.ts +0 -160
  163. package/src/generate/drums/percussion.ts +0 -121
  164. package/src/generate/drums/rng.ts +0 -7
  165. package/src/generate/drums/swing.ts +0 -71
  166. package/src/generate/groove/index.ts +0 -351
  167. package/src/generate/harmonize/index.ts +0 -451
  168. package/src/generate/index.ts +0 -58
  169. package/src/generate/motif/index.ts +0 -422
  170. package/src/generate/progression/index.ts +0 -362
  171. package/src/generate/reharmony/index.ts +0 -323
  172. package/src/generate/rhythm/index.ts +0 -175
  173. package/src/index.ts +0 -13
  174. package/src/model/chord.ts +0 -442
  175. package/src/model/index.ts +0 -15
  176. package/src/model/interval.ts +0 -82
  177. package/src/model/key.ts +0 -266
  178. package/src/model/note.ts +0 -176
  179. package/src/model/progression.ts +0 -161
  180. package/src/model/shared.ts +0 -12
  181. package/src/theory/chord/index.ts +0 -375
  182. package/src/theory/chordscale/index.ts +0 -374
  183. package/src/theory/counterpoint/index.ts +0 -230
  184. package/src/theory/harmony/index.ts +0 -77
  185. package/src/theory/index.ts +0 -112
  186. package/src/theory/safety/index.ts +0 -488
  187. package/src/theory/scale/degrees.ts +0 -123
  188. package/src/theory/scale/index.ts +0 -28
  189. package/src/theory/scale/key.ts +0 -56
  190. package/src/theory/scale/masks.ts +0 -153
  191. package/src/theory/spelling/index.ts +0 -249
  192. package/src/theory/symbol/index.ts +0 -268
  193. package/src/theory/voicing/index.ts +0 -5
  194. package/src/theory/voicing/internal.ts +0 -168
  195. package/src/theory/voicing/leading.ts +0 -112
  196. package/src/theory/voicing/satb.ts +0 -216
  197. package/src/theory/voicing/styled.ts +0 -199
  198. package/tsconfig.json +0 -23
@@ -1,1823 +1,173 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/theory/index.ts
21
- var theory_exports = {};
22
- __export(theory_exports, {
23
- BLUES_MASK: () => BLUES_MASK,
24
- CHROMATIC_MASK: () => CHROMATIC_MASK,
25
- DORIAN_MASK: () => DORIAN_MASK,
26
- HARMONIC_MINOR_MASK: () => HARMONIC_MINOR_MASK,
27
- LOCRIAN_MASK: () => LOCRIAN_MASK,
28
- LYDIAN_MASK: () => LYDIAN_MASK,
29
- MAJOR_MASK: () => MAJOR_MASK,
30
- MAJOR_PENTATONIC_MASK: () => MAJOR_PENTATONIC_MASK,
31
- MELODIC_MINOR_MASK: () => MELODIC_MINOR_MASK,
32
- MINOR_PENTATONIC_MASK: () => MINOR_PENTATONIC_MASK,
33
- MIXOLYDIAN_MASK: () => MIXOLYDIAN_MASK,
34
- NAMED_SCALES: () => NAMED_SCALES,
35
- NATURAL_MINOR_MASK: () => NATURAL_MINOR_MASK,
36
- NoteSafety: () => NoteSafety,
37
- OCTATONIC_HALF_WHOLE_MASK: () => OCTATONIC_HALF_WHOLE_MASK,
38
- OCTATONIC_WHOLE_HALF_MASK: () => OCTATONIC_WHOLE_HALF_MASK,
39
- PHRYGIAN_MASK: () => PHRYGIAN_MASK,
40
- ReasonFlag: () => ReasonFlag,
41
- SATB_RANGES: () => SATB_RANGES,
42
- WHOLE_TONE_MASK: () => WHOLE_TONE_MASK,
43
- availableTensions: () => availableTensions,
44
- avoidNotes: () => avoidNotes,
45
- chordFromDegree: () => chordFromDegree,
46
- chordPitchClasses: () => chordPitchClasses,
47
- chordQualities: () => chordQualities,
48
- chordScaleReport: () => chordScaleReport,
49
- chordScales: () => chordScales,
50
- chordToneRole: () => chordToneRole,
51
- createsHiddenParallelPerfect: () => createsHiddenParallelPerfect,
52
- createsParallelOctave: () => createsParallelOctave,
53
- createsParallelPerfect: () => createsParallelPerfect,
54
- createsParallelUnison: () => createsParallelUnison,
55
- createsVerticalDissonance: () => createsVerticalDissonance,
56
- createsVoiceCrossing: () => createsVoiceCrossing,
57
- createsVoiceOverlap: () => createsVoiceOverlap,
58
- diatonicPitchClasses: () => diatonicPitchClasses,
59
- diatonicSeventh: () => diatonicSeventh,
60
- diatonicTriad: () => diatonicTriad,
61
- enumerateSafePitches: () => enumerateSafePitches,
62
- evaluateSafety: () => evaluateSafety,
63
- exceedsSpacing: () => exceedsSpacing,
64
- formatChordSymbol: () => formatChordSymbol,
65
- isForbiddenMelodicLeap: () => isForbiddenMelodicLeap,
66
- isLeadingToneResolution: () => isLeadingToneResolution,
67
- isScaleTone: () => isScaleTone,
68
- majorKey: () => majorKey,
69
- makeChord: () => makeChord,
70
- maskFromOffsets: () => maskFromOffsets,
71
- minorKey: () => minorKey,
72
- nearestScaleTone: () => nearestScaleTone,
73
- nextVoicing: () => nextVoicing,
74
- noteNames: () => noteNames,
75
- parseChordSymbol: () => parseChordSymbol,
76
- pitchToScaleDegree: () => pitchToScaleDegree,
77
- roleOf: () => roleOf,
78
- scaleByName: () => scaleByName,
79
- scaleMatchesChord: () => scaleMatchesChord,
80
- scaleTonesInDegreeOrder: () => scaleTonesInDegreeOrder,
81
- scalesForChanges: () => scalesForChanges,
82
- spellChord: () => spellChord,
83
- spellPitchClass: () => spellPitchClass,
84
- spellPitchClasses: () => spellPitchClasses,
85
- spellScale: () => spellScale,
86
- transposeChordSymbol: () => transposeChordSymbol,
87
- voiceChord: () => voiceChord,
88
- voiceChordStyled: () => voiceChordStyled,
89
- voiceLeadingCost: () => voiceLeadingCost,
90
- voiceProgression: () => voiceProgression
91
- });
92
- module.exports = __toCommonJS(theory_exports);
93
-
94
- // src/theory/scale/degrees.ts
95
- function pitchClass(pitch) {
96
- return (Math.trunc(pitch) % 12 + 12) % 12;
97
- }
98
- function scaleOffset(pitch, key) {
99
- return (pitchClass(pitch) - pitchClass(key.rootPc) + 12) % 12;
100
- }
101
- function isScaleTone(pitch, key) {
102
- return (key.modeMask12 >> scaleOffset(pitch, key) & 1) === 1;
103
- }
104
- function nearestScaleTone(pitch, key) {
105
- const base = Math.round(pitch);
106
- for (let distance = 0; distance < 12; distance += 1) {
107
- const lower = base - distance;
108
- if (isScaleTone(lower, key)) {
109
- return lower;
110
- }
111
- const higher = base + distance;
112
- if (isScaleTone(higher, key)) {
113
- return higher;
114
- }
115
- }
116
- return base;
117
- }
118
- function pitchToScaleDegree(pitch, key) {
119
- const offset = scaleOffset(pitch, key);
120
- if ((key.modeMask12 >> offset & 1) === 0) {
121
- return -1;
122
- }
123
- let degree = 0;
124
- for (let n = 0; n < offset; n += 1) {
125
- if ((key.modeMask12 >> n & 1) === 1) {
126
- degree += 1;
127
- }
128
- }
129
- return degree;
130
- }
131
- function diatonicPitchClasses(key) {
132
- const root = pitchClass(key.rootPc);
133
- const pcs = [];
134
- for (let n = 0; n < 12; n += 1) {
135
- if ((key.modeMask12 >> n & 1) === 1) {
136
- pcs.push((root + n) % 12);
137
- }
138
- }
139
- return pcs.sort((a, b) => a - b);
140
- }
141
- function scaleTonesInDegreeOrder(key) {
142
- const root = pitchClass(key.rootPc);
143
- const pcs = [];
144
- for (let n = 0; n < 12; n += 1) {
145
- if ((key.modeMask12 >> n & 1) === 1) {
146
- pcs.push((root + n) % 12);
147
- }
148
- }
149
- return pcs;
150
- }
151
-
152
- // src/theory/scale/masks.ts
153
- function maskFromOffsets(offsets) {
154
- let mask = 1;
155
- for (const offset of offsets) {
156
- mask |= 1 << (offset % 12 + 12) % 12;
157
- }
158
- return mask;
159
- }
160
- var MAJOR_MASK = 2741;
161
- var NATURAL_MINOR_MASK = 1453;
162
- var HARMONIC_MINOR_MASK = maskFromOffsets([0, 2, 3, 5, 7, 8, 11]);
163
- var MELODIC_MINOR_MASK = maskFromOffsets([0, 2, 3, 5, 7, 9, 11]);
164
- var DORIAN_MASK = maskFromOffsets([0, 2, 3, 5, 7, 9, 10]);
165
- var PHRYGIAN_MASK = maskFromOffsets([0, 1, 3, 5, 7, 8, 10]);
166
- var LYDIAN_MASK = maskFromOffsets([0, 2, 4, 6, 7, 9, 11]);
167
- var MIXOLYDIAN_MASK = maskFromOffsets([0, 2, 4, 5, 7, 9, 10]);
168
- var LOCRIAN_MASK = maskFromOffsets([0, 1, 3, 5, 6, 8, 10]);
169
- var MAJOR_PENTATONIC_MASK = maskFromOffsets([0, 2, 4, 7, 9]);
170
- var MINOR_PENTATONIC_MASK = maskFromOffsets([0, 3, 5, 7, 10]);
171
- var BLUES_MASK = maskFromOffsets([0, 3, 5, 6, 7, 10]);
172
- var WHOLE_TONE_MASK = maskFromOffsets([0, 2, 4, 6, 8, 10]);
173
- var OCTATONIC_HALF_WHOLE_MASK = maskFromOffsets([0, 1, 3, 4, 6, 7, 9, 10]);
174
- var OCTATONIC_WHOLE_HALF_MASK = maskFromOffsets([0, 2, 3, 5, 6, 8, 9, 11]);
175
- var CHROMATIC_MASK = 4095;
176
- var NAMED_SCALES = {
177
- major: MAJOR_MASK,
178
- ionian: MAJOR_MASK,
179
- naturalMinor: NATURAL_MINOR_MASK,
180
- aeolian: NATURAL_MINOR_MASK,
181
- harmonicMinor: HARMONIC_MINOR_MASK,
182
- melodicMinor: MELODIC_MINOR_MASK,
183
- dorian: DORIAN_MASK,
184
- phrygian: PHRYGIAN_MASK,
185
- lydian: LYDIAN_MASK,
186
- mixolydian: MIXOLYDIAN_MASK,
187
- locrian: LOCRIAN_MASK,
188
- majorPentatonic: MAJOR_PENTATONIC_MASK,
189
- minorPentatonic: MINOR_PENTATONIC_MASK,
190
- blues: BLUES_MASK,
191
- wholeTone: WHOLE_TONE_MASK,
192
- octatonicHalfWhole: OCTATONIC_HALF_WHOLE_MASK,
193
- octatonicWholeHalf: OCTATONIC_WHOLE_HALF_MASK,
194
- chromatic: CHROMATIC_MASK
195
- };
196
-
197
- // src/theory/scale/key.ts
198
- function majorKey(rootPc) {
199
- return { rootPc: (rootPc % 12 + 12) % 12, modeMask12: MAJOR_MASK };
200
- }
201
- function minorKey(rootPc) {
202
- return { rootPc: (rootPc % 12 + 12) % 12, modeMask12: NATURAL_MINOR_MASK };
203
- }
204
- function scaleByName(name, rootPc) {
205
- const mask = NAMED_SCALES[name];
206
- if (mask === void 0) {
207
- throw new Error(`Unknown scale: ${name}`);
208
- }
209
- return { rootPc: (rootPc % 12 + 12) % 12, modeMask12: mask };
210
- }
211
-
212
- // src/theory/chord/index.ts
213
- var QUALITY_INTERVALS = {
214
- maj: [0, 4, 7],
215
- min: [0, 3, 7],
216
- dim: [0, 3, 6],
217
- aug: [0, 4, 8],
218
- majb5: [0, 4, 6],
219
- maj7: [0, 4, 7, 11],
220
- min7: [0, 3, 7, 10],
221
- dom7: [0, 4, 7, 10],
222
- dim7: [0, 3, 6, 9],
223
- m7b5: [0, 3, 6, 10],
224
- minMaj7: [0, 3, 7, 11],
225
- aug7: [0, 4, 8, 10],
226
- augMaj7: [0, 4, 8, 11],
227
- "6": [0, 4, 7, 9],
228
- min6: [0, 3, 7, 9],
229
- "6/9": [0, 4, 7, 9, 14],
230
- sus2: [0, 2, 7],
231
- sus4: [0, 5, 7],
232
- add9: [0, 4, 7, 14],
233
- add11: [0, 4, 7, 17],
234
- maj9: [0, 4, 7, 11, 14],
235
- min9: [0, 3, 7, 10, 14],
236
- dom9: [0, 4, 7, 10, 14],
237
- "7b9": [0, 4, 7, 10, 13],
238
- "7#9": [0, 4, 7, 10, 15],
239
- "7#11": [0, 4, 7, 10, 18],
240
- "7b13": [0, 4, 7, 10, 20],
241
- "11": [0, 7, 10, 14, 17],
242
- "13": [0, 4, 7, 10, 14, 21],
243
- "5": [0, 7]
244
- };
245
- function pitchClass2(value) {
246
- return (Math.trunc(value) % 12 + 12) % 12;
247
- }
248
- function chordQualities() {
249
- return Object.keys(QUALITY_INTERVALS);
250
- }
251
- function chordFromDegree(degree, ext, key) {
252
- const tones = scaleTonesInDegreeOrder(key);
253
- const length = tones.length;
254
- const index = length > 0 ? (degree % length + length) % length : 0;
255
- const rootPc = tones[index] ?? pitchClass2(key.rootPc);
256
- return { rootPc, quality: ext, intervals: [...QUALITY_INTERVALS[ext]] };
257
- }
258
- function makeChord(rootPc, quality, bassPc) {
259
- const chord = {
260
- rootPc: pitchClass2(rootPc),
261
- quality,
262
- intervals: [...QUALITY_INTERVALS[quality]]
263
- };
264
- if (bassPc !== void 0) {
265
- chord.bassPc = pitchClass2(bassPc);
266
- }
267
- return chord;
268
- }
269
- function chordPitchClasses(chord) {
270
- const set = /* @__PURE__ */ new Set();
271
- for (const interval of chord.intervals) {
272
- set.add(pitchClass2(chord.rootPc + interval));
273
- }
274
- return [...set].sort((a, b) => a - b);
275
- }
276
- function chordToneOffsets(chord) {
277
- return new Set(chord.intervals.map((i) => (i % 12 + 12) % 12));
278
- }
279
- function chordToneRole(pitch, chord) {
280
- const interval = (pitchClass2(pitch) - pitchClass2(chord.rootPc) + 12) % 12;
281
- const tones = chordToneOffsets(chord);
282
- if (interval === 0) {
283
- return "root";
284
- }
285
- if (interval === 3 || interval === 4) {
286
- return tones.has(interval) ? "third" : null;
287
- }
288
- if (interval === 7) {
289
- return tones.has(7) ? "fifth" : null;
290
- }
291
- if (interval === 6) {
292
- return tones.has(6) && !tones.has(7) ? "fifth" : null;
293
- }
294
- if (interval === 8) {
295
- return tones.has(8) && !tones.has(7) ? "fifth" : null;
296
- }
297
- if (interval === 9) {
298
- const hasHigherSeventh = tones.has(10) || tones.has(11);
299
- const isDiminishedSeventh = tones.has(3) && tones.has(6) && !hasHigherSeventh;
300
- if (isDiminishedSeventh) {
301
- return "seventh";
302
- }
303
- if (tones.has(9) && !hasHigherSeventh) {
304
- return "sixth";
305
- }
306
- return null;
307
- }
308
- if (interval === 10 || interval === 11) {
309
- return tones.has(interval) ? "seventh" : null;
310
- }
311
- return null;
312
- }
313
- function classifyTriad(thirdIc, fifthIc) {
314
- if (thirdIc === 4 && fifthIc === 8) {
315
- return "aug";
316
- }
317
- if (thirdIc === 4 && fifthIc === 6) {
318
- return "majb5";
319
- }
320
- if (thirdIc === 3 && fifthIc === 6) {
321
- return "dim";
322
- }
323
- if (thirdIc === 3) {
324
- return "min";
325
- }
326
- return "maj";
327
- }
328
- function classifySeventh(thirdIc, fifthIc, seventhIc) {
329
- if (thirdIc === 3 && fifthIc === 6 && seventhIc === 9) {
330
- return "dim7";
331
- }
332
- if (thirdIc === 3 && fifthIc === 6 && seventhIc === 10) {
333
- return "m7b5";
334
- }
335
- if (thirdIc === 3 && seventhIc === 11) {
336
- return "minMaj7";
337
- }
338
- if (thirdIc === 3) {
339
- return "min7";
340
- }
341
- if (fifthIc === 8 && seventhIc === 10) {
342
- return "aug7";
343
- }
344
- if (fifthIc === 8 && seventhIc === 11) {
345
- return "augMaj7";
346
- }
347
- if (seventhIc === 11) {
348
- return "maj7";
349
- }
350
- return "dom7";
351
- }
352
- function stackThirds(degree, key, size) {
353
- const tones = scaleTonesInDegreeOrder(key);
354
- const length = tones.length;
355
- if (length !== 7) {
356
- throw new Error(
357
- `diatonic chord stacking requires a heptatonic scale (received ${length} tones)`
358
- );
359
- }
360
- const idx = (step) => ((degree + step) % length + length) % length;
361
- const rootPc = tones[idx(0)] ?? pitchClass2(key.rootPc);
362
- const offsets = [0, 2, 4, 6].slice(0, size).map((step) => {
363
- const pc = tones[idx(step)] ?? rootPc;
364
- return ((pc - rootPc) % 12 + 12) % 12;
365
- });
366
- const thirdIc = offsets[1] ?? 4;
367
- const fifthIc = offsets[2] ?? 7;
368
- const quality = size === 3 ? classifyTriad(thirdIc, fifthIc) : classifySeventh(thirdIc, fifthIc, offsets[3] ?? 11);
369
- return { rootPc, quality, intervals: offsets };
370
- }
371
- function diatonicTriad(degree, key) {
372
- return stackThirds(degree, key, 3);
373
- }
374
- function diatonicSeventh(degree, key) {
375
- return stackThirds(degree, key, 4);
376
- }
377
-
378
- // src/theory/chordscale/index.ts
379
- function pitchClass3(value) {
380
- return (Math.trunc(value) % 12 + 12) % 12;
381
- }
382
- function popcount12(mask) {
383
- let count = 0;
384
- for (let n = 0; n < 12; n += 1) {
385
- count += mask >> n & 1;
386
- }
387
- return count;
388
- }
389
- function maskHasPitchClass(mask, scaleRootPc, pc) {
390
- const offset = pitchClass3(pc - scaleRootPc);
391
- return (mask >> offset & 1) === 1;
392
- }
393
- function scaleMatchesChord(chordPcs, scaleMask, scaleRootPc) {
394
- for (const pc of chordPcs) {
395
- if (!maskHasPitchClass(scaleMask, scaleRootPc, pc)) {
396
- return false;
397
- }
398
- }
399
- return true;
400
- }
401
- var ALIASED_SCALE_NAMES = /* @__PURE__ */ new Set(["major", "naturalMinor"]);
402
- var HEPTATONIC_SIZE = 7;
403
- function chordScales(chord) {
404
- const chordPcs = chordPitchClasses(chord);
405
- const rootPc = pitchClass3(chord.rootPc);
406
- const ranked = [];
407
- const seenMasks = /* @__PURE__ */ new Set();
408
- for (const name of Object.keys(NAMED_SCALES)) {
409
- if (name === "chromatic" || ALIASED_SCALE_NAMES.has(name)) {
410
- continue;
411
- }
412
- const mask = NAMED_SCALES[name];
413
- if (mask === void 0 || seenMasks.has(mask)) {
414
- continue;
415
- }
416
- seenMasks.add(mask);
417
- if (scaleMatchesChord(chordPcs, mask, rootPc)) {
418
- const size = popcount12(mask);
419
- ranked.push({ name, extra: size - chordPcs.length, size });
420
- }
421
- }
422
- if (ranked.length === 0) {
423
- if (NAMED_SCALES.chromatic !== void 0) {
424
- return [{ name: "chromatic", rootPc }];
425
- }
426
- return [];
427
- }
428
- const preferHeptatonic = chordPcs.length <= 3;
429
- ranked.sort((a, b) => {
430
- if (preferHeptatonic && a.size === HEPTATONIC_SIZE !== (b.size === HEPTATONIC_SIZE)) {
431
- return a.size === HEPTATONIC_SIZE ? -1 : 1;
432
- }
433
- if (a.extra !== b.extra) {
434
- return a.extra - b.extra;
435
- }
436
- if (a.size !== b.size) {
437
- return a.size - b.size;
438
- }
439
- return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
440
- });
441
- return ranked.map((entry) => ({ name: entry.name, rootPc }));
442
- }
443
- function avoidNotes(chord, scaleName) {
444
- const mask = NAMED_SCALES[scaleName];
445
- if (mask === void 0) {
446
- return [];
447
- }
448
- const rootPc = pitchClass3(chord.rootPc);
449
- const chordPcs = chordPitchClasses(chord);
450
- if (!scaleMatchesChord(chordPcs, mask, rootPc)) {
451
- return [];
452
- }
453
- const chordSet = new Set(chordPcs);
454
- const avoid = [];
455
- for (let pc = 0; pc < 12; pc += 1) {
456
- if (!maskHasPitchClass(mask, rootPc, pc) || chordSet.has(pc)) {
457
- continue;
458
- }
459
- if (chordSet.has(pitchClass3(pc - 1))) {
460
- avoid.push(pc);
461
- }
462
- }
463
- return avoid.sort((a, b) => a - b);
464
- }
465
- function availableTensions(chord, scaleName) {
466
- const mask = NAMED_SCALES[scaleName];
467
- if (mask === void 0) {
468
- return [];
469
- }
470
- const rootPc = pitchClass3(chord.rootPc);
471
- const chordPcs = chordPitchClasses(chord);
472
- if (!scaleMatchesChord(chordPcs, mask, rootPc)) {
473
- return [];
474
- }
475
- const chordSet = new Set(chordPcs);
476
- const avoidSet = new Set(avoidNotes(chord, scaleName));
477
- const tensions = [];
478
- for (let pc = 0; pc < 12; pc += 1) {
479
- if (!maskHasPitchClass(mask, rootPc, pc) || chordSet.has(pc) || avoidSet.has(pc)) {
480
- continue;
481
- }
482
- tensions.push(pc);
483
- }
484
- return tensions.sort((a, b) => a - b);
485
- }
486
- function chordScaleReport(chord, limit) {
487
- const matches = chordScales(chord);
488
- const chosen = limit === void 0 ? matches : matches.slice(0, Math.max(0, limit));
489
- return chosen.map((match) => ({
490
- name: match.name,
491
- rootPc: match.rootPc,
492
- avoid: avoidNotes(chord, match.name),
493
- tensions: availableTensions(chord, match.name)
494
- }));
495
- }
496
- var RANK_PENALTY = 0.01;
497
- function scalePitchClassSet(name, rootPc) {
498
- const mask = NAMED_SCALES[name];
499
- const pcs = /* @__PURE__ */ new Set();
500
- if (mask === void 0) {
501
- return pcs;
502
- }
503
- for (let n = 0; n < 12; n += 1) {
504
- if ((mask >> n & 1) === 1) {
505
- pcs.add(pitchClass3(rootPc + n));
506
- }
507
- }
508
- return pcs;
509
- }
510
- function symmetricDifferenceSize(a, b) {
511
- let count = 0;
512
- for (const pc of a) {
513
- if (!b.has(pc)) {
514
- count += 1;
515
- }
516
- }
517
- for (const pc of b) {
518
- if (!a.has(pc)) {
519
- count += 1;
520
- }
521
- }
522
- return count;
523
- }
524
- function scalesForChanges(chords) {
525
- if (chords.length === 0) {
526
- return [];
527
- }
528
- const candidateLists = chords.map((chord) => chordScales(chord));
529
- const pcSets = candidateLists.map(
530
- (candidates) => candidates.map((match) => scalePitchClassSet(match.name, match.rootPc))
531
- );
532
- const first = candidateLists[0] ?? [];
533
- const dp = [first.map((_, j) => j * RANK_PENALTY)];
534
- const back = [first.map(() => -1)];
535
- for (let i = 1; i < candidateLists.length; i += 1) {
536
- const candidates = candidateLists[i] ?? [];
537
- const prevCosts = dp[i - 1] ?? [];
538
- const prevSets = pcSets[i - 1] ?? [];
539
- const curSets = pcSets[i] ?? [];
540
- const stageCosts = [];
541
- const stageBack = [];
542
- for (let j = 0; j < candidates.length; j += 1) {
543
- let bestCost = Number.POSITIVE_INFINITY;
544
- let bestPrev = -1;
545
- for (let k = 0; k < prevCosts.length; k += 1) {
546
- const transition = symmetricDifferenceSize(
547
- prevSets[k] ?? /* @__PURE__ */ new Set(),
548
- curSets[j] ?? /* @__PURE__ */ new Set()
549
- );
550
- const cost = (prevCosts[k] ?? 0) + transition;
551
- if (cost < bestCost) {
552
- bestCost = cost;
553
- bestPrev = k;
554
- }
555
- }
556
- stageCosts.push(bestCost + j * RANK_PENALTY);
557
- stageBack.push(bestPrev);
558
- }
559
- dp.push(stageCosts);
560
- back.push(stageBack);
561
- }
562
- const lastCosts = dp[dp.length - 1] ?? [];
563
- let bestFinal = 0;
564
- for (let j = 1; j < lastCosts.length; j += 1) {
565
- if ((lastCosts[j] ?? Number.POSITIVE_INFINITY) < (lastCosts[bestFinal] ?? 0)) {
566
- bestFinal = j;
567
- }
568
- }
569
- const chosenIndices = new Array(candidateLists.length);
570
- let current = bestFinal;
571
- for (let i = candidateLists.length - 1; i >= 0; i -= 1) {
572
- chosenIndices[i] = current;
573
- current = back[i]?.[current] ?? -1;
574
- }
575
- return chords.map((chord, i) => {
576
- const candidates = candidateLists[i] ?? [];
577
- const scale = candidates[chosenIndices[i] ?? 0] ?? { name: "chromatic", rootPc: chord.rootPc };
578
- return { chord, scale };
579
- });
580
- }
581
-
582
- // src/core/interval/index.ts
583
- function simpleInterval(semitones) {
584
- return Math.abs(semitones) % 12;
585
- }
586
- function isConsonantInterval(semitones, twoVoice = true) {
587
- const pc = simpleInterval(semitones);
588
- if (pc === 5) {
589
- return !twoVoice;
590
- }
591
- return pc === 0 || pc === 3 || pc === 4 || pc === 7 || pc === 8 || pc === 9;
592
- }
593
-
594
- // src/theory/counterpoint/index.ts
595
- function pitchClass4(pitch) {
596
- return (Math.trunc(pitch) % 12 + 12) % 12;
597
- }
598
- function createsVoiceCrossing(upperPitch, lowerPitch) {
599
- return upperPitch < lowerPitch;
600
- }
601
- function createsVerticalDissonance(a, b, twoVoice) {
602
- return !isConsonantInterval(a - b, twoVoice);
603
- }
604
- function isForbiddenMelodicLeap(prev, cur) {
605
- const semis = Math.abs(cur - prev);
606
- return semis === 6 || semis === 10 || semis === 11 || semis > 12;
607
- }
608
- function simpleClass(semitones) {
609
- return Math.abs(semitones) % 12;
610
- }
611
- function isPerfectClass(cls) {
612
- return cls === 0 || cls === 7;
613
- }
614
- function similarMotion(aMove, bMove) {
615
- return aMove !== 0 && bMove !== 0 && aMove > 0 === bMove > 0;
616
- }
617
- function bothVoicesMove(aMove, bMove) {
618
- return aMove !== 0 && bMove !== 0;
619
- }
620
- function createsParallelPerfect(aPrev, aCur, bPrev, bCur) {
621
- if (!bothVoicesMove(aCur - aPrev, bCur - bPrev)) {
622
- return false;
623
- }
624
- const nowClass = simpleClass(aCur - bCur);
625
- const prevClass = simpleClass(aPrev - bPrev);
626
- return isPerfectClass(nowClass) && nowClass === prevClass;
627
- }
628
- function createsParallelOctave(aPrev, aCur, bPrev, bCur) {
629
- if (!similarMotion(aCur - aPrev, bCur - bPrev)) {
630
- return false;
631
- }
632
- return simpleClass(aCur - bCur) === 0 && simpleClass(aPrev - bPrev) === 0;
633
- }
634
- function createsParallelUnison(aPrev, aCur, bPrev, bCur) {
635
- if (aCur === aPrev || bCur === bPrev) {
636
- return false;
637
- }
638
- return aCur === bCur && aPrev === bPrev;
639
- }
640
- function createsHiddenParallelPerfect(aPrev, aCur, bPrev, bCur) {
641
- const aMove = aCur - aPrev;
642
- const bMove = bCur - bPrev;
643
- if (!similarMotion(aMove, bMove)) {
644
- return false;
645
- }
646
- const nowClass = simpleClass(aCur - bCur);
647
- const prevClass = simpleClass(aPrev - bPrev);
648
- if (!isPerfectClass(nowClass) || prevClass === nowClass) {
649
- return false;
650
- }
651
- const upperMove = aCur >= bCur ? aMove : bMove;
652
- if (Math.abs(upperMove) <= 2) {
653
- return false;
654
- }
655
- return true;
656
- }
657
- function createsVoiceOverlap(upperPrev, upperCur, lowerPrev, lowerCur) {
658
- return upperCur < lowerPrev || lowerCur > upperPrev;
659
- }
660
- function exceedsSpacing(upperPitch, lowerPitch, maxSemitones = 12) {
661
- return Math.abs(upperPitch - lowerPitch) > maxSemitones;
662
- }
663
- function isLeadingToneResolution(prev, cur, key) {
664
- const tonic = pitchClass4(key.rootPc);
665
- const leading = (tonic + 11) % 12;
666
- if (pitchClass4(prev) !== leading || pitchClass4(cur) !== tonic) {
667
- return false;
668
- }
669
- return cur > prev && cur - prev <= 2;
670
- }
671
-
672
- // src/theory/harmony/index.ts
673
- function roleOf(pitch, chord, chordId = 0) {
674
- const interval = ((Math.trunc(pitch) - chord.rootPc) % 12 + 12) % 12;
675
- const tones = new Set(chord.intervals.map((i) => (i % 12 + 12) % 12));
676
- const hasThird = tones.has(3) || tones.has(4);
677
- const isSuspendedTone = !hasThird && (interval === 5 && tones.has(5) || interval === 2 && tones.has(2));
678
- const chordRole = chordToneRole(pitch, chord);
679
- let role;
680
- let lock;
681
- if (isSuspendedTone) {
682
- role = "third";
683
- lock = "quality";
684
- } else if (chordRole !== null) {
685
- role = chordRole;
686
- lock = chordRole === "root" ? "identity" : chordRole === "third" ? "quality" : "voicing";
687
- } else {
688
- role = "tension";
689
- lock = "voicing";
690
- }
691
- return { role, lock, belongsToChordId: chordId };
692
- }
693
-
694
- // src/core/validation/index.ts
695
- var DEFAULT_GENERATION_BUDGET = 1e6;
696
- function assertFiniteNumber(value, name) {
697
- if (!Number.isFinite(value)) {
698
- throw new RangeError(`${name} must be finite; received ${value}`);
699
- }
700
- return value;
701
- }
702
- function assertInteger(value, name, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
703
- assertFiniteNumber(value, name);
704
- if (!Number.isSafeInteger(value) || value < min || value > max) {
705
- throw new RangeError(`${name} must be an integer in [${min}, ${max}]; received ${value}`);
706
- }
707
- return value;
708
- }
709
- function assertPositiveInt(value, name, max = DEFAULT_GENERATION_BUDGET) {
710
- return assertInteger(value, name, 1, max);
711
- }
712
- function assertGenerationBudget(estimated, name, limit = DEFAULT_GENERATION_BUDGET) {
713
- assertFiniteNumber(estimated, name);
714
- assertPositiveInt(limit, `${name} limit`, Number.MAX_SAFE_INTEGER);
715
- if (estimated < 0 || estimated > limit) {
716
- throw new RangeError(`${name} exceeds the generation budget ${limit}; received ${estimated}`);
717
- }
718
- return estimated;
719
- }
720
-
721
- // src/theory/safety/index.ts
722
- var NoteSafety = /* @__PURE__ */ ((NoteSafety2) => {
723
- NoteSafety2[NoteSafety2["Safe"] = 0] = "Safe";
724
- NoteSafety2[NoteSafety2["Warning"] = 1] = "Warning";
725
- NoteSafety2[NoteSafety2["Dissonant"] = 2] = "Dissonant";
726
- return NoteSafety2;
727
- })(NoteSafety || {});
728
- var ReasonFlag = /* @__PURE__ */ ((ReasonFlag2) => {
729
- ReasonFlag2[ReasonFlag2["ChordTone"] = 1] = "ChordTone";
730
- ReasonFlag2[ReasonFlag2["Tension"] = 2] = "Tension";
731
- ReasonFlag2[ReasonFlag2["AvoidNote"] = 4] = "AvoidNote";
732
- ReasonFlag2[ReasonFlag2["ScaleTone"] = 8] = "ScaleTone";
733
- ReasonFlag2[ReasonFlag2["NonScale"] = 16] = "NonScale";
734
- ReasonFlag2[ReasonFlag2["OutOfRange"] = 32] = "OutOfRange";
735
- ReasonFlag2[ReasonFlag2["Tritone"] = 64] = "Tritone";
736
- ReasonFlag2[ReasonFlag2["LargeLeap"] = 128] = "LargeLeap";
737
- ReasonFlag2[ReasonFlag2["MinorSecond"] = 256] = "MinorSecond";
738
- ReasonFlag2[ReasonFlag2["MajorSeventh"] = 512] = "MajorSeventh";
739
- ReasonFlag2[ReasonFlag2["VerticalDissonance"] = 1024] = "VerticalDissonance";
740
- ReasonFlag2[ReasonFlag2["ParallelPerfect"] = 2048] = "ParallelPerfect";
741
- ReasonFlag2[ReasonFlag2["HiddenParallel"] = 4096] = "HiddenParallel";
742
- ReasonFlag2[ReasonFlag2["VoiceCrossing"] = 8192] = "VoiceCrossing";
743
- ReasonFlag2[ReasonFlag2["Suspension"] = 16384] = "Suspension";
744
- ReasonFlag2[ReasonFlag2["NeedsResolution"] = 32768] = "NeedsResolution";
745
- return ReasonFlag2;
746
- })(ReasonFlag || {});
747
- var SUGGESTION_WINDOW = 12;
748
- var MAX_SUGGESTIONS = 3;
749
- var REASON_SEVERITY = [
750
- [2 /* Tension */, 1 /* Warning */, 1 /* Warning */],
751
- [4 /* AvoidNote */, 1 /* Warning */, 2 /* Dissonant */],
752
- [8 /* ScaleTone */, 1 /* Warning */, 1 /* Warning */],
753
- [16 /* NonScale */, 2 /* Dissonant */, 2 /* Dissonant */],
754
- [32 /* OutOfRange */, 1 /* Warning */, 1 /* Warning */],
755
- [64 /* Tritone */, 2 /* Dissonant */, 2 /* Dissonant */],
756
- [128 /* LargeLeap */, 1 /* Warning */, 2 /* Dissonant */],
757
- [1024 /* VerticalDissonance */, 2 /* Dissonant */, 2 /* Dissonant */],
758
- [2048 /* ParallelPerfect */, 1 /* Warning */, 2 /* Dissonant */],
759
- [4096 /* HiddenParallel */, 1 /* Warning */, 2 /* Dissonant */],
760
- [8192 /* VoiceCrossing */, 1 /* Warning */, 2 /* Dissonant */],
761
- [16384 /* Suspension */, 2 /* Dissonant */, 2 /* Dissonant */],
762
- [32768 /* NeedsResolution */, 1 /* Warning */, 2 /* Dissonant */]
763
- ];
764
- function minimumSafetyForReasons(reasons, profile) {
765
- let minimum = 0 /* Safe */;
766
- const severityIndex = profile === "strict" ? 2 : 1;
767
- for (const entry of REASON_SEVERITY) {
768
- if (reasons & entry[0]) {
769
- minimum = Math.max(minimum, entry[severityIndex]);
770
- }
771
- }
772
- return minimum;
773
- }
774
- function pitchClass5(pitch) {
775
- return (Math.trunc(pitch) % 12 + 12) % 12;
776
- }
777
- function intervalAboveRoot(pitch, chord) {
778
- return ((pitchClass5(pitch) - pitchClass5(chord.rootPc)) % 12 + 12) % 12;
779
- }
780
- function isChordMember(pitch, chord) {
781
- return chordPitchClasses(chord).includes(pitchClass5(pitch));
782
- }
783
- function avoidsFourth(chord) {
784
- return chord.intervals.includes(4) && !chord.intervals.includes(5);
785
- }
786
- function avoidsMajorSeventh(chord) {
787
- return chord.intervals.includes(4) && chord.intervals.includes(10);
788
- }
789
- function stepResolution(pitch, chord) {
790
- for (let delta = 1; delta <= 2; delta += 1) {
791
- if (isChordMember(pitch - delta, chord)) {
792
- return pitch - delta;
793
- }
794
- }
795
- return void 0;
796
- }
797
- function evaluateSafety(q) {
798
- assertSafetyContext(q);
799
- assertFiniteNumber(q.candidatePitch, "candidatePitch");
800
- return evaluateInternal(q, true);
801
- }
802
- function assertSafetyContext(q) {
803
- if (q.prevPitch !== void 0) assertFiniteNumber(q.prevPitch, "prevPitch");
804
- if (q.vocalLow !== void 0) assertFiniteNumber(q.vocalLow, "vocalLow");
805
- if (q.vocalHigh !== void 0) assertFiniteNumber(q.vocalHigh, "vocalHigh");
806
- if (q.vocalLow !== void 0 && q.vocalHigh !== void 0 && q.vocalLow > q.vocalHigh) {
807
- throw new RangeError("vocalLow must not exceed vocalHigh");
808
- }
809
- assertGenerationBudget(q.otherVoices.length, "other voices");
810
- for (let index = 0; index < q.otherVoices.length; index += 1) {
811
- const voice = q.otherVoices[index];
812
- if (!voice) continue;
813
- assertFiniteNumber(voice.pitch, `otherVoices[${index}].pitch`);
814
- if (voice.prevPitch !== void 0) {
815
- assertFiniteNumber(voice.prevPitch, `otherVoices[${index}].prevPitch`);
816
- }
817
- }
818
- }
819
- function evaluateInternal(q, collectSuggestions) {
820
- let reasons = 0;
821
- let level = 0 /* Safe */;
822
- let resolveTo;
823
- const raise = (l) => {
824
- if (l > level) {
825
- level = l;
826
- }
827
- };
828
- const avoidSeverity = q.profile === "strict" ? 2 /* Dissonant */ : 1 /* Warning */;
829
- const parallelSeverity = avoidSeverity;
830
- const pitch = q.candidatePitch;
831
- if (q.vocalLow !== void 0 && pitch < q.vocalLow || q.vocalHigh !== void 0 && pitch > q.vocalHigh) {
832
- reasons |= 32 /* OutOfRange */;
833
- raise(1 /* Warning */);
834
- }
835
- const inScale = isScaleTone(pitch, q.key);
836
- const chord = q.chord;
837
- if (chord && isChordMember(pitch, chord)) {
838
- reasons |= 1 /* ChordTone */;
839
- } else if (chord) {
840
- const ic = intervalAboveRoot(pitch, chord);
841
- const isTension = ic === 2 || ic === 5 || ic === 9;
842
- const avoid = ic === 5 && avoidsFourth(chord) || ic === 11 && avoidsMajorSeventh(chord);
843
- if (avoid) {
844
- reasons |= 4 /* AvoidNote */;
845
- if (isTension) {
846
- reasons |= 2 /* Tension */;
847
- }
848
- reasons |= 32768 /* NeedsResolution */;
849
- resolveTo = stepResolution(pitch, chord);
850
- raise(avoidSeverity);
851
- } else if (isTension && inScale) {
852
- reasons |= 2 /* Tension */;
853
- raise(1 /* Warning */);
854
- } else if (inScale) {
855
- reasons |= 8 /* ScaleTone */;
856
- raise(1 /* Warning */);
857
- } else {
858
- reasons |= 16 /* NonScale */;
859
- raise(2 /* Dissonant */);
860
- }
861
- } else if (inScale) {
862
- reasons |= 8 /* ScaleTone */;
863
- raise(1 /* Warning */);
864
- } else {
865
- reasons |= 16 /* NonScale */;
866
- raise(2 /* Dissonant */);
867
- }
868
- if (chord && !(chord.intervals.includes(4) && chord.intervals.includes(10))) {
869
- const ic = intervalAboveRoot(pitch, chord);
870
- const toneOffsets = chord.intervals.map((i) => (i % 12 + 12) % 12);
871
- if (toneOffsets.some((t) => Math.abs(ic - t) === 6)) {
872
- reasons |= 64 /* Tritone */;
873
- }
874
- }
875
- if (q.prevPitch !== void 0) {
876
- const pc = Math.abs(pitch - q.prevPitch) % 12;
877
- if (pc === 6) {
878
- reasons |= 64 /* Tritone */;
879
- raise(2 /* Dissonant */);
880
- }
881
- if (isForbiddenMelodicLeap(q.prevPitch, pitch)) {
882
- reasons |= 128 /* LargeLeap */;
883
- raise(parallelSeverity);
884
- }
885
- if (pc === 1) {
886
- reasons |= 256 /* MinorSecond */;
887
- }
888
- if (pc === 11) {
889
- reasons |= 512 /* MajorSeventh */;
890
- }
891
- }
892
- if (q.strongBeat) {
893
- const twoVoice = q.otherVoices.length === 1;
894
- const prev = q.prevPitch;
895
- for (const ov of q.otherVoices) {
896
- if (!createsVerticalDissonance(pitch, ov.pitch, twoVoice)) {
897
- continue;
898
- }
899
- reasons |= 1024 /* VerticalDissonance */;
900
- raise(2 /* Dissonant */);
901
- if (prev !== void 0 && pitch === prev && ov.prevPitch !== void 0 && !createsVerticalDissonance(prev, ov.prevPitch, twoVoice)) {
902
- reasons |= 16384 /* Suspension */;
903
- }
904
- }
905
- }
906
- if (q.prevPitch !== void 0) {
907
- const prev = q.prevPitch;
908
- for (const ov of q.otherVoices) {
909
- if (ov.prevPitch === void 0) {
910
- continue;
911
- }
912
- if (createsParallelPerfect(prev, pitch, ov.prevPitch, ov.pitch)) {
913
- reasons |= 2048 /* ParallelPerfect */;
914
- raise(parallelSeverity);
915
- }
916
- if (createsHiddenParallelPerfect(prev, pitch, ov.prevPitch, ov.pitch)) {
917
- reasons |= 4096 /* HiddenParallel */;
918
- raise(parallelSeverity);
919
- }
920
- const crossedNow = pitch - ov.pitch;
921
- const crossedPrev = prev - ov.prevPitch;
922
- if (crossedNow !== 0 && crossedPrev !== 0 && crossedNow > 0 !== crossedPrev > 0) {
923
- reasons |= 8192 /* VoiceCrossing */;
924
- raise(parallelSeverity);
925
- }
926
- }
927
- }
928
- raise(minimumSafetyForReasons(reasons, q.profile));
929
- const result = { safety: level, reasons, rationale: describe(reasons, q) };
930
- if (resolveTo !== void 0) {
931
- result.resolveTo = resolveTo;
932
- }
933
- if (collectSuggestions && level !== 0 /* Safe */) {
934
- const suggestions = findSafeNearby(q, pitch);
935
- if (suggestions.length > 0) {
936
- result.suggestions = suggestions;
937
- }
938
- }
939
- return result;
940
- }
941
- function findSafeNearby(q, candidate) {
942
- const out = [];
943
- for (let d = 1; d <= SUGGESTION_WINDOW; d += 1) {
944
- for (const p of [candidate - d, candidate + d]) {
945
- if (evaluateInternal({ ...q, candidatePitch: p }, false).safety === 0 /* Safe */) {
946
- out.push(p);
947
- if (out.length >= MAX_SUGGESTIONS) {
948
- return out;
949
- }
950
- }
951
- }
952
- }
953
- return out;
954
- }
955
- function describe(reasons, q) {
956
- if (reasons & 32 /* OutOfRange */) {
957
- return "Outside the target vocal range";
958
- }
959
- if (reasons & 16384 /* Suspension */) {
960
- return "Prepared suspension \u2014 a held consonance now dissonant, awaiting resolution";
961
- }
962
- if (reasons & 1024 /* VerticalDissonance */) {
963
- return "Dissonant against a sounding voice on a strong beat";
964
- }
965
- if (reasons & 4 /* AvoidNote */) {
966
- return "Avoid note \u2014 clashes with a chord tone a semitone away";
967
- }
968
- if (reasons & 2048 /* ParallelPerfect */) {
969
- return "Parallel perfect interval with another voice";
970
- }
971
- if (reasons & 4096 /* HiddenParallel */) {
972
- return "Hidden perfect interval by similar motion";
973
- }
974
- if (reasons & 8192 /* VoiceCrossing */) {
975
- return "Crosses another voice";
976
- }
977
- if (reasons & 1 /* ChordTone */) {
978
- return "Chord tone";
979
- }
980
- if (reasons & 2 /* Tension */) {
981
- return "Chord tension";
982
- }
983
- if (reasons & 16 /* NonScale */) {
984
- return "Outside the key";
985
- }
986
- if (reasons & 8 /* ScaleTone */) {
987
- return "Scale tone, not in the chord";
988
- }
989
- return q.chord ? "Placeable" : "No chord context";
990
- }
991
- function enumerateSafePitches(q, pitchLow, pitchHigh) {
992
- assertSafetyContext(q);
993
- const chordTones = [];
994
- const others = [];
995
- assertInteger(pitchLow, "pitchLow");
996
- assertInteger(pitchHigh, "pitchHigh");
997
- if (pitchLow > pitchHigh) {
998
- throw new RangeError(`pitchLow must not exceed pitchHigh; received ${pitchLow} > ${pitchHigh}`);
999
- }
1000
- assertGenerationBudget(pitchHigh - pitchLow + 1, "safe pitch candidates");
1001
- for (let pitch = pitchHigh; pitch >= pitchLow; pitch -= 1) {
1002
- const result = evaluateInternal({ ...q, candidatePitch: pitch }, false);
1003
- if (result.safety === 2 /* Dissonant */) {
1004
- continue;
1005
- }
1006
- if (result.reasons & 1 /* ChordTone */) {
1007
- chordTones.push(pitch);
1008
- } else {
1009
- others.push(pitch);
1010
- }
1011
- }
1012
- return [...chordTones, ...others];
1013
- }
1014
-
1015
- // src/core/pitch/index.ts
1016
- var LETTER_SEMITONES = [0, 2, 4, 5, 7, 9, 11];
1017
- var LETTER_NAMES = ["C", "D", "E", "F", "G", "A", "B"];
1018
- function mod12(n) {
1019
- return (n % 12 + 12) % 12;
1020
- }
1021
- function mod7(n) {
1022
- return (n % 7 + 7) % 7;
1023
- }
1024
- function parseNote(text) {
1025
- const match = /^([A-Ga-g])([#x]*|b*)(-?\d+)?$/.exec(text.trim());
1026
- if (!match) {
1027
- throw new Error(`Invalid note: ${text}`);
1028
- }
1029
- const letterGlyph = (match[1] ?? "").toUpperCase();
1030
- const letter = LETTER_NAMES.indexOf(letterGlyph);
1031
- let alter = 0;
1032
- for (const ch of match[2] ?? "") {
1033
- if (ch === "#") {
1034
- alter += 1;
1035
- } else if (ch === "x") {
1036
- alter += 2;
1037
- } else if (ch === "b") {
1038
- alter -= 1;
1039
- }
1040
- }
1041
- const note = { letter, alter };
1042
- if (match[3] !== void 0) {
1043
- note.octave = Number.parseInt(match[3], 10);
1044
- }
1045
- return note;
1046
- }
1047
- function formatAlter(alter) {
1048
- if (alter > 0) {
1049
- return "#".repeat(alter);
1050
- }
1051
- if (alter < 0) {
1052
- return "b".repeat(-alter);
1053
- }
1054
- return "";
1055
- }
1056
- function formatNote(note) {
1057
- const glyph = LETTER_NAMES[mod7(note.letter)] ?? "C";
1058
- const octave = note.octave === void 0 ? "" : String(note.octave);
1059
- return `${glyph}${formatAlter(note.alter)}${octave}`;
1060
- }
1061
- function noteToPitchClass(note) {
1062
- const natural = LETTER_SEMITONES[mod7(note.letter)] ?? 0;
1063
- return mod12(natural + note.alter);
1064
- }
1065
- var SHARP_SPELLING = [
1066
- [0, 0],
1067
- [0, 1],
1068
- [1, 0],
1069
- [1, 1],
1070
- [2, 0],
1071
- [3, 0],
1072
- [3, 1],
1073
- [4, 0],
1074
- [4, 1],
1075
- [5, 0],
1076
- [5, 1],
1077
- [6, 0]
1078
- ];
1079
- var FLAT_SPELLING = [
1080
- [0, 0],
1081
- [1, -1],
1082
- [1, 0],
1083
- [2, -1],
1084
- [2, 0],
1085
- [3, 0],
1086
- [4, -1],
1087
- [4, 0],
1088
- [5, -1],
1089
- [5, 0],
1090
- [6, -1],
1091
- [6, 0]
1092
- ];
1093
- function midiToNote(midi, spelling = "sharp") {
1094
- const rounded = Math.round(midi);
1095
- const pc = mod12(rounded);
1096
- const octave = Math.floor(rounded / 12) - 1;
1097
- const table = spelling === "sharp" ? SHARP_SPELLING : FLAT_SPELLING;
1098
- const entry = table[pc] ?? [0, 0];
1099
- return { letter: entry[0], alter: entry[1], octave };
1100
- }
1101
-
1102
- // src/theory/spelling/index.ts
1103
- var LETTER_SEMITONES2 = [0, 2, 4, 5, 7, 9, 11];
1104
- var CHROMATIC_SPELLING = {
1105
- 1: { degreeOffset: 1, alter: -1 },
1106
- // b2
1107
- 3: { degreeOffset: 2, alter: -1 },
1108
- // b3
1109
- 6: { degreeOffset: 3, alter: 1 },
1110
- // #4
1111
- 8: { degreeOffset: 5, alter: -1 },
1112
- // b6
1113
- 9: { degreeOffset: 5, alter: 1 },
1114
- // #6 (raised sixth of a minor key)
1115
- 10: { degreeOffset: 6, alter: -1 },
1116
- // b7
1117
- 11: { degreeOffset: 6, alter: 1 }
1118
- // #7 (raised leading tone of a minor key)
1119
- };
1120
- function mod122(n) {
1121
- return (n % 12 + 12) % 12;
1122
- }
1123
- function mod72(n) {
1124
- return (n % 7 + 7) % 7;
1125
- }
1126
- function naturalPc(letter) {
1127
- return LETTER_SEMITONES2[mod72(letter)] ?? 0;
1128
- }
1129
- function alterFor(letter, pc) {
1130
- let d = mod122(pc - naturalPc(letter));
1131
- if (d > 6) {
1132
- d -= 12;
1133
- }
1134
- return d;
1135
- }
1136
- function isHeptatonic(key) {
1137
- return scaleTonesInDegreeOrder(key).length === 7;
1138
- }
1139
- function spellPitchClass(pc, tonic, key) {
1140
- const tonicPc = mod122(naturalPc(tonic.letter) + tonic.alter);
1141
- const offset = mod122(pc - tonicPc);
1142
- const tones = scaleTonesInDegreeOrder(key);
1143
- if (isHeptatonic(key)) {
1144
- const degree = tones.indexOf(mod122(pc));
1145
- if (degree >= 0) {
1146
- const letter = mod72(tonic.letter + degree);
1147
- return { letter, alter: alterFor(letter, pc) };
1148
- }
1149
- const chromatic = CHROMATIC_SPELLING[offset];
1150
- if (chromatic) {
1151
- const letter = mod72(tonic.letter + chromatic.degreeOffset);
1152
- return { letter, alter: alterFor(letter, pc) };
1153
- }
1154
- }
1155
- for (let letter = 0; letter < 7; letter += 1) {
1156
- if (naturalPc(letter) === mod122(pc)) {
1157
- return { letter, alter: 0 };
1158
- }
1159
- }
1160
- const belowLetter = mod72([0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6][mod122(pc)] ?? 0);
1161
- return { letter: belowLetter, alter: alterFor(belowLetter, pc) };
1162
- }
1163
- function spellScale(tonic, key) {
1164
- return scaleTonesInDegreeOrder(key).map((pc) => spellPitchClass(pc, tonic, key));
1165
- }
1166
- function spellPitchClasses(pcs, tonic, key) {
1167
- return pcs.map((pc) => spellPitchClass(pc, tonic, key));
1168
- }
1169
- function chordLetterOffset(interval, chord) {
1170
- switch (interval) {
1171
- case 0:
1172
- case 12:
1173
- return 0;
1174
- case 1:
1175
- case 2:
1176
- case 13:
1177
- case 14:
1178
- return 1;
1179
- case 3:
1180
- case 4:
1181
- case 15:
1182
- case 16:
1183
- return 2;
1184
- case 5:
1185
- case 17:
1186
- case 18:
1187
- return 3;
1188
- case 6:
1189
- case 7:
1190
- case 8:
1191
- case 19:
1192
- return 4;
1193
- case 9:
1194
- return chord.quality === "dim7" ? 6 : 5;
1195
- case 20:
1196
- case 21:
1197
- return 5;
1198
- case 10:
1199
- case 11:
1200
- case 22:
1201
- case 23:
1202
- return 6;
1203
- default: {
1204
- const octaves = Math.floor(Math.max(0, interval) / 12);
1205
- const simple = mod122(interval);
1206
- const simpleOffset = [0, 1, 1, 2, 2, 3, 4, 4, 4, 5, 6, 6][simple] ?? 0;
1207
- return octaves * 7 + simpleOffset;
1208
- }
1209
- }
1210
- }
1211
- function spellChordFromRoot(chord, root) {
1212
- return chord.intervals.map((interval) => {
1213
- const letter = mod72(root.letter + chordLetterOffset(interval, chord));
1214
- const pc = mod122(chord.rootPc + interval);
1215
- return { letter, alter: alterFor(letter, pc) };
1216
- });
1217
- }
1218
- function spellChord(chord, tonic, key) {
1219
- const root = spellPitchClass(chord.rootPc, tonic, key);
1220
- return spellChordFromRoot(chord, root);
1221
- }
1222
- function noteNames(notes) {
1223
- return notes.map(formatNote);
1224
- }
1225
-
1226
- // src/theory/symbol/index.ts
1227
- var ROOT_RE = /^[A-Ga-g](?:#{1,2}|b{1,2})?/;
1228
- var BASS_RE = /^[A-Ga-g](?:#{1,2}|b{1,2})?$/;
1229
- var QUALITY_MAP = {
1230
- "": "maj",
1231
- m: "min",
1232
- min: "min",
1233
- "-": "min",
1234
- dim: "dim",
1235
- "\xB0": "dim",
1236
- aug: "aug",
1237
- "+": "aug",
1238
- maj7: "maj7",
1239
- M7: "maj7",
1240
- \u0394: "maj7",
1241
- \u03947: "maj7",
1242
- m7: "min7",
1243
- min7: "min7",
1244
- "-7": "min7",
1245
- "7": "dom7",
1246
- dim7: "dim7",
1247
- "\xB07": "dim7",
1248
- m7b5: "m7b5",
1249
- \u00F8: "m7b5",
1250
- \u00F87: "m7b5",
1251
- min7b5: "m7b5",
1252
- mMaj7: "minMaj7",
1253
- mM7: "minMaj7",
1254
- minMaj7: "minMaj7",
1255
- aug7: "aug7",
1256
- "+7": "aug7",
1257
- "7#5": "aug7",
1258
- augMaj7: "augMaj7",
1259
- augM7: "augMaj7",
1260
- "+maj7": "augMaj7",
1261
- "+M7": "augMaj7",
1262
- majb5: "majb5",
1263
- "maj(b5)": "majb5",
1264
- "(b5)": "majb5",
1265
- "6": "6",
1266
- m6: "min6",
1267
- min6: "min6",
1268
- "6/9": "6/9",
1269
- "69": "6/9",
1270
- sus2: "sus2",
1271
- sus: "sus4",
1272
- sus4: "sus4",
1273
- add9: "add9",
1274
- add11: "add11",
1275
- maj9: "maj9",
1276
- M9: "maj9",
1277
- m9: "min9",
1278
- min9: "min9",
1279
- "9": "dom9",
1280
- "7b9": "7b9",
1281
- "7#9": "7#9",
1282
- "7#11": "7#11",
1283
- "7b13": "7b13",
1284
- "11": "11",
1285
- "13": "13",
1286
- "5": "5"
1287
- };
1288
- var CANONICAL_SUFFIX = {
1289
- maj: "",
1290
- min: "m",
1291
- dim: "dim",
1292
- aug: "aug",
1293
- maj7: "maj7",
1294
- min7: "m7",
1295
- dom7: "7",
1296
- dim7: "dim7",
1297
- m7b5: "m7b5",
1298
- minMaj7: "mMaj7",
1299
- aug7: "aug7",
1300
- augMaj7: "augMaj7",
1301
- majb5: "maj(b5)",
1302
- "6": "6",
1303
- min6: "m6",
1304
- "6/9": "6/9",
1305
- sus2: "sus2",
1306
- sus4: "sus4",
1307
- add9: "add9",
1308
- add11: "add11",
1309
- maj9: "maj9",
1310
- min9: "m9",
1311
- dom9: "9",
1312
- "7b9": "7b9",
1313
- "7#9": "7#9",
1314
- "7#11": "7#11",
1315
- "7b13": "7b13",
1316
- "11": "11",
1317
- "13": "13",
1318
- "5": "5"
1319
- };
1320
- function pitchClass6(value) {
1321
- return (Math.trunc(value) % 12 + 12) % 12;
1322
- }
1323
- function makeSpelledChord(root, quality, bass) {
1324
- const chord = makeChord(
1325
- noteToPitchClass(root),
1326
- quality,
1327
- bass === void 0 ? void 0 : noteToPitchClass(bass)
1328
- );
1329
- chord.rootSpelling = { letter: root.letter, alter: root.alter };
1330
- if (bass !== void 0) {
1331
- chord.bassSpelling = { letter: bass.letter, alter: bass.alter };
1332
- }
1333
- return chord;
1334
- }
1335
- function parseChordSymbol(text) {
1336
- const trimmed = text.trim();
1337
- const rootMatch = ROOT_RE.exec(trimmed);
1338
- if (!rootMatch) {
1339
- throw new Error(`Invalid chord symbol: ${text}`);
1340
- }
1341
- const rootToken = rootMatch[0];
1342
- const rootNote = parseNote(rootToken);
1343
- const rest = trimmed.slice(rootToken.length);
1344
- const slashIndex = rest.lastIndexOf("/");
1345
- if (slashIndex !== -1) {
1346
- const before = rest.slice(0, slashIndex);
1347
- const after = rest.slice(slashIndex + 1);
1348
- const beforeQuality = QUALITY_MAP[before];
1349
- if (beforeQuality !== void 0 && BASS_RE.test(after)) {
1350
- return makeSpelledChord(rootNote, beforeQuality, parseNote(after));
1351
- }
1352
- }
1353
- const quality = QUALITY_MAP[rest];
1354
- if (quality === void 0) {
1355
- throw new Error(`Unrecognized chord quality: ${text}`);
1356
- }
1357
- return makeSpelledChord(rootNote, quality);
1358
- }
1359
- function pitchClassName(pc, hint, flats) {
1360
- if (flats === void 0 && hint !== void 0 && noteToPitchClass(hint) === pc) {
1361
- return formatNote(hint);
1362
- }
1363
- const note = midiToNote(60 + pc, flats ? "flat" : "sharp");
1364
- return formatNote({ letter: note.letter, alter: note.alter });
1365
- }
1366
- function formatChordSymbol(chord, opts) {
1367
- const rootPc = pitchClass6(chord.rootPc);
1368
- const rootName = pitchClassName(rootPc, chord.rootSpelling, opts?.flats);
1369
- const suffix = CANONICAL_SUFFIX[chord.quality];
1370
- let symbol = `${rootName}${suffix}`;
1371
- if (chord.bassPc !== void 0 && pitchClass6(chord.bassPc) !== rootPc) {
1372
- symbol += `/${pitchClassName(pitchClass6(chord.bassPc), chord.bassSpelling, opts?.flats)}`;
1373
- }
1374
- return symbol;
1375
- }
1376
- function transposeChordSymbol(text, semitones, opts) {
1377
- const chord = parseChordSymbol(text);
1378
- const transposed = { ...chord, rootPc: pitchClass6(chord.rootPc + semitones) };
1379
- if (chord.bassPc !== void 0) {
1380
- transposed.bassPc = pitchClass6(chord.bassPc + semitones);
1381
- }
1382
- return formatChordSymbol(transposed, opts);
1383
- }
1384
-
1385
- // src/theory/voicing/internal.ts
1386
- var DEFAULT_MAX_SPACING = 12;
1387
- var VIOLATION_PENALTY = 1e3;
1388
- var MISSING_TONE_PENALTY = 500;
1389
- var POOR_DOUBLING_PENALTY = 4;
1390
- var MAX_CANDIDATES = 4e3;
1391
- function pitchClass7(value) {
1392
- return (Math.trunc(value) % 12 + 12) % 12;
1393
- }
1394
- function pitchesForPc(pc, range) {
1395
- const result = [];
1396
- for (let midi = Math.ceil(range.min); midi <= range.max; midi += 1) {
1397
- if (pitchClass7(midi) === pc) {
1398
- result.push(midi);
1399
- }
1400
- }
1401
- const center = (range.min + range.max) / 2;
1402
- return result.sort((a, b) => {
1403
- const da = Math.abs(a - center);
1404
- const db = Math.abs(b - center);
1405
- return da === db ? a - b : da - db;
1406
- });
1407
- }
1408
- function enumerateVoicings(chord, ranges, maxSpacing) {
1409
- const chordPcs = chordPitchClasses(chord);
1410
- const bassPc = pitchClass7(chord.bassPc ?? chord.rootPc);
1411
- const results = [];
1412
- const current = [];
1413
- const build = (voice) => {
1414
- if (results.length >= MAX_CANDIDATES) {
1415
- return;
1416
- }
1417
- if (voice === ranges.length) {
1418
- results.push([...current]);
1419
- return;
1420
- }
1421
- const range = ranges[voice];
1422
- if (range === void 0) {
1423
- return;
1424
- }
1425
- const pcs = voice === 0 ? [bassPc] : chordPcs;
1426
- const prev = current[voice - 1];
1427
- for (const pc of pcs) {
1428
- for (const pitch of pitchesForPc(pc, range)) {
1429
- if (prev !== void 0) {
1430
- if (pitch < prev) {
1431
- continue;
1432
- }
1433
- const spacingLimit = voice === 1 ? maxSpacing + 12 : maxSpacing;
1434
- if (pitch - prev > spacingLimit) {
1435
- continue;
1436
- }
1437
- }
1438
- current.push(pitch);
1439
- build(voice + 1);
1440
- current.pop();
1441
- }
1442
- }
1443
- };
1444
- build(0);
1445
- return results;
1446
- }
1447
- function structuralPenalty(pitches, chord) {
1448
- const counts = /* @__PURE__ */ new Map();
1449
- for (const pitch of pitches) {
1450
- const pc = pitchClass7(pitch);
1451
- counts.set(pc, (counts.get(pc) ?? 0) + 1);
1452
- }
1453
- let penalty = 0;
1454
- for (const pc of chordPitchClasses(chord)) {
1455
- if (!counts.has(pc)) {
1456
- penalty += MISSING_TONE_PENALTY;
1457
- }
1458
- }
1459
- const rootPc = pitchClass7(chord.rootPc);
1460
- const fifthPc = pitchClass7(chord.rootPc + 7);
1461
- for (const [pc, count] of counts) {
1462
- if (count > 1 && pc !== rootPc && pc !== fifthPc) {
1463
- penalty += (count - 1) * POOR_DOUBLING_PENALTY;
1464
- }
1465
- }
1466
- return penalty;
1467
- }
1468
- function violationCount(prev, cur, maxSpacing) {
1469
- let count = 0;
1470
- for (let lower = 0; lower < cur.length; lower += 1) {
1471
- for (let upper = lower + 1; upper < cur.length; upper += 1) {
1472
- const prevLower = prev[lower];
1473
- const prevUpper = prev[upper];
1474
- const curLower = cur[lower];
1475
- const curUpper = cur[upper];
1476
- if (prevLower === void 0 || prevUpper === void 0 || curLower === void 0 || curUpper === void 0) {
1477
- continue;
1478
- }
1479
- if (createsParallelPerfect(prevUpper, curUpper, prevLower, curLower)) {
1480
- count += 1;
1481
- }
1482
- if (createsVoiceCrossing(curUpper, curLower)) {
1483
- count += 1;
1484
- }
1485
- if (upper === lower + 1) {
1486
- if (createsVoiceOverlap(prevUpper, curUpper, prevLower, curLower)) {
1487
- count += 1;
1488
- }
1489
- if (lower > 0 && exceedsSpacing(curUpper, curLower, maxSpacing)) {
1490
- count += 1;
1491
- }
1492
- }
1493
- }
1494
- }
1495
- return count;
1496
- }
1497
-
1498
- // src/theory/voicing/satb.ts
1499
- var SATB_RANGES = [
1500
- { min: 40, max: 60 },
1501
- { min: 48, max: 67 },
1502
- { min: 55, max: 74 },
1503
- { min: 60, max: 79 }
1504
- ];
1505
- var DERIVED_LOW = 40;
1506
- var DERIVED_HIGH = 79;
1507
- var DERIVED_SPAN = 19;
1508
- function resolveRanges(opts) {
1509
- if (opts?.ranges !== void 0) {
1510
- if (opts.ranges.length === 0) {
1511
- throw new Error("ranges must contain at least one voice range");
1512
- }
1513
- assertGenerationBudget(opts.ranges.length, "voice ranges", 128);
1514
- return opts.ranges.map((range, index) => {
1515
- assertFiniteNumber(range.min, `ranges[${index}].min`);
1516
- assertFiniteNumber(range.max, `ranges[${index}].max`);
1517
- if (range.min > range.max) {
1518
- throw new RangeError(`ranges[${index}].min must not exceed max`);
1519
- }
1520
- assertGenerationBudget(
1521
- Math.floor(range.max) - Math.ceil(range.min) + 1,
1522
- `ranges[${index}] span`,
1523
- 4096
1524
- );
1525
- return { ...range };
1526
- });
1527
- }
1528
- const voices = opts?.voices ?? 4;
1529
- assertPositiveInt(voices, "voices", 128);
1530
- if (voices === 4) {
1531
- return SATB_RANGES.map((range) => ({ ...range }));
1532
- }
1533
- if (voices === 1) {
1534
- return [{ min: DERIVED_LOW, max: DERIVED_HIGH }];
1535
- }
1536
- const ranges = [];
1537
- for (let i = 0; i < voices; i += 1) {
1538
- const min = Math.round(
1539
- DERIVED_LOW + i * (DERIVED_HIGH - DERIVED_SPAN - DERIVED_LOW) / (voices - 1)
1540
- );
1541
- ranges.push({ min, max: min + DERIVED_SPAN });
1542
- }
1543
- return ranges;
1544
- }
1545
- function voiceChord(chord, opts) {
1546
- const ranges = resolveRanges(opts);
1547
- const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;
1548
- assertFiniteNumber(maxSpacing, "maxSpacing");
1549
- if (maxSpacing < 0) throw new RangeError("maxSpacing must be non-negative");
1550
- const candidates = enumerateVoicings(chord, ranges, maxSpacing);
1551
- let best;
1552
- let bestScore = Number.POSITIVE_INFINITY;
1553
- for (const candidate of candidates) {
1554
- let score = structuralPenalty(candidate, chord);
1555
- for (let i = 0; i < candidate.length; i += 1) {
1556
- const pitch = candidate[i];
1557
- const range = ranges[i];
1558
- if (pitch === void 0 || range === void 0) {
1559
- continue;
1560
- }
1561
- score += Math.abs(pitch - (range.min + range.max) / 2);
1562
- }
1563
- if (score < bestScore) {
1564
- bestScore = score;
1565
- best = candidate;
1566
- }
1567
- }
1568
- if (best === void 0) {
1569
- throw new Error("no voicing satisfies the given ranges");
1570
- }
1571
- return best;
1572
- }
1573
- function voiceProgression(chords, opts) {
1574
- assertGenerationBudget(chords.length * 4e3, "voiced progression search");
1575
- const ranges = resolveRanges(opts);
1576
- const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;
1577
- assertFiniteNumber(maxSpacing, "maxSpacing");
1578
- if (maxSpacing < 0) throw new RangeError("maxSpacing must be non-negative");
1579
- const result = [];
1580
- let prev;
1581
- for (const chord of chords) {
1582
- if (prev === void 0) {
1583
- prev = voiceChord(chord, opts);
1584
- result.push(prev);
1585
- continue;
1586
- }
1587
- const candidates = enumerateVoicings(chord, ranges, maxSpacing);
1588
- let best;
1589
- let bestScore = Number.POSITIVE_INFINITY;
1590
- for (const candidate of candidates) {
1591
- const score = structuralPenalty(candidate, chord) + voiceLeadingCost(prev, candidate) + VIOLATION_PENALTY * violationCount(prev, candidate, maxSpacing);
1592
- if (score < bestScore) {
1593
- bestScore = score;
1594
- best = candidate;
1595
- }
1596
- }
1597
- if (best === void 0) {
1598
- throw new Error("no voicing satisfies the given ranges");
1599
- }
1600
- result.push(best);
1601
- prev = best;
1602
- }
1603
- return result;
1604
- }
1605
-
1606
- // src/theory/voicing/leading.ts
1607
- var HIDDEN_PERFECT_PENALTY = 6;
1608
- function voiceLeadingCost(from, to) {
1609
- if (from.length !== to.length) {
1610
- return Number.POSITIVE_INFINITY;
1611
- }
1612
- let total = 0;
1613
- for (let i = 0; i < from.length; i += 1) {
1614
- const a = from[i];
1615
- const b = to[i];
1616
- if (a === void 0 || b === void 0) {
1617
- continue;
1618
- }
1619
- total += Math.abs(b - a);
1620
- }
1621
- if (from.length >= 2) {
1622
- const bassPrev = from[0];
1623
- const bassCur = to[0];
1624
- const sopPrev = from[from.length - 1];
1625
- const sopCur = to[to.length - 1];
1626
- if (bassPrev !== void 0 && bassCur !== void 0 && sopPrev !== void 0 && sopCur !== void 0 && createsHiddenParallelPerfect(bassPrev, bassCur, sopPrev, sopCur)) {
1627
- total += HIDDEN_PERFECT_PENALTY;
1628
- }
1629
- }
1630
- return total;
1631
- }
1632
- function nextVoicing(current, chord, opts) {
1633
- const ranges = opts?.ranges !== void 0 || opts?.voices !== void 0 ? resolveRanges(opts) : current.map((pitch) => {
1634
- const centre = Math.min(127, Math.max(0, pitch));
1635
- return { min: Math.max(0, centre - 12), max: Math.min(127, centre + 12) };
1636
- });
1637
- const maxSpacing = opts?.maxSpacing ?? DEFAULT_MAX_SPACING;
1638
- const candidates = enumerateVoicings(chord, ranges, maxSpacing);
1639
- let best;
1640
- let bestScore = Number.POSITIVE_INFINITY;
1641
- for (const candidate of candidates) {
1642
- const score = structuralPenalty(candidate, chord) + voiceLeadingCost(current, candidate) + VIOLATION_PENALTY * violationCount(current, candidate, maxSpacing);
1643
- if (score < bestScore) {
1644
- bestScore = score;
1645
- best = candidate;
1646
- }
1647
- }
1648
- if (best === void 0) {
1649
- throw new Error("no voicing satisfies the given ranges");
1650
- }
1651
- return best;
1652
- }
1653
-
1654
- // src/theory/voicing/styled.ts
1655
- var DEFAULT_STYLE_OCTAVE = 4;
1656
- function dedupePcs(pcs) {
1657
- const seen = /* @__PURE__ */ new Set();
1658
- const result = [];
1659
- for (const pc of pcs) {
1660
- if (!seen.has(pc)) {
1661
- seen.add(pc);
1662
- result.push(pc);
1663
- }
1664
- }
1665
- return result;
1666
- }
1667
- function lowestPitchAtOrAbove(pc, floor) {
1668
- return floor + ((pc - pitchClass7(floor)) % 12 + 12) % 12;
1669
- }
1670
- function nearestPc(target, pcs) {
1671
- let best = pcs[0] ?? target;
1672
- let bestDist = 12;
1673
- for (const pc of pcs) {
1674
- const dist = Math.min(((pc - target) % 12 + 12) % 12, ((target - pc) % 12 + 12) % 12);
1675
- if (dist < bestDist) {
1676
- bestDist = dist;
1677
- best = pc;
1678
- }
1679
- }
1680
- return best;
1681
- }
1682
- function voiceChordStyled(chord, opts) {
1683
- const style = opts?.style ?? "close";
1684
- const octave = opts?.octave ?? DEFAULT_STYLE_OCTAVE;
1685
- assertInteger(octave, "styled voicing octave", -10, 10);
1686
- if (opts?.topNote !== void 0) {
1687
- assertFiniteNumber(opts.topNote, "styled voicing topNote");
1688
- }
1689
- const base = 12 * (octave + 1);
1690
- const rootPc = pitchClass7(chord.rootPc);
1691
- const bassPc = pitchClass7(chord.bassPc ?? chord.rootPc);
1692
- const omitRoot = style === "rootless" || opts?.rootless === true;
1693
- let order = dedupePcs(chord.intervals.map((interval) => pitchClass7(chord.rootPc + interval)));
1694
- const bassIndex = order.indexOf(bassPc);
1695
- if (bassIndex > 0) {
1696
- order = [...order.slice(bassIndex), ...order.slice(0, bassIndex)];
1697
- } else if (bassIndex < 0) {
1698
- order = [bassPc, ...order];
1699
- }
1700
- if (style === "shell") {
1701
- const roles = order.map((pc) => chordToneRole(pc, chord));
1702
- const guide = roles.includes("seventh") ? "seventh" : roles.includes("sixth") ? "sixth" : "fifth";
1703
- order = order.filter((_pc, i) => {
1704
- const role = roles[i];
1705
- return _pc === bassPc || role === "root" || role === "third" || role === guide;
1706
- });
1707
- }
1708
- if (omitRoot) {
1709
- order = order.filter((pc) => pc !== rootPc || chord.bassPc !== void 0 && pc === bassPc);
1710
- }
1711
- if (order.length === 0) {
1712
- return [];
1713
- }
1714
- if (opts?.topNote !== void 0) {
1715
- const target = order.includes(pitchClass7(opts.topNote)) ? pitchClass7(opts.topNote) : nearestPc(pitchClass7(opts.topNote), order);
1716
- const targetIndex = order.indexOf(target);
1717
- order = [...order.slice(targetIndex + 1), ...order.slice(0, targetIndex + 1)];
1718
- }
1719
- const stack = [];
1720
- let prev;
1721
- for (const pc of order) {
1722
- if (prev === void 0) {
1723
- prev = lowestPitchAtOrAbove(pc, base);
1724
- } else {
1725
- let delta = ((pc - pitchClass7(prev)) % 12 + 12) % 12;
1726
- if (delta === 0) {
1727
- delta = 12;
1728
- }
1729
- prev += delta;
1730
- }
1731
- stack.push(prev);
1732
- }
1733
- if (style === "drop2" && stack.length >= 2) {
1734
- stack[stack.length - 2] = (stack[stack.length - 2] ?? 0) - 12;
1735
- } else if (style === "drop3" && stack.length >= 3) {
1736
- stack[stack.length - 3] = (stack[stack.length - 3] ?? 0) - 12;
1737
- }
1738
- if (chord.bassPc !== void 0) {
1739
- const bassIndexInStack = stack.findIndex((pitch) => pitchClass7(pitch) === bassPc);
1740
- if (bassIndexInStack >= 0) {
1741
- const otherLowest = Math.min(
1742
- ...stack.filter((_pitch, index) => index !== bassIndexInStack),
1743
- Number.POSITIVE_INFINITY
1744
- );
1745
- while ((stack[bassIndexInStack] ?? 0) >= otherLowest) {
1746
- stack[bassIndexInStack] = (stack[bassIndexInStack] ?? 0) - 12;
1747
- }
1748
- }
1749
- }
1750
- return stack.sort((a, b) => a - b);
1751
- }
1752
- // Annotate the CommonJS export names for ESM import in node:
1753
- 0 && (module.exports = {
1754
- BLUES_MASK,
1755
- CHROMATIC_MASK,
1756
- DORIAN_MASK,
1757
- HARMONIC_MINOR_MASK,
1758
- LOCRIAN_MASK,
1759
- LYDIAN_MASK,
1760
- MAJOR_MASK,
1761
- MAJOR_PENTATONIC_MASK,
1762
- MELODIC_MINOR_MASK,
1763
- MINOR_PENTATONIC_MASK,
1764
- MIXOLYDIAN_MASK,
1765
- NAMED_SCALES,
1766
- NATURAL_MINOR_MASK,
1767
- NoteSafety,
1768
- OCTATONIC_HALF_WHOLE_MASK,
1769
- OCTATONIC_WHOLE_HALF_MASK,
1770
- PHRYGIAN_MASK,
1771
- ReasonFlag,
1772
- SATB_RANGES,
1773
- WHOLE_TONE_MASK,
1774
- availableTensions,
1775
- avoidNotes,
1776
- chordFromDegree,
1777
- chordPitchClasses,
1778
- chordQualities,
1779
- chordScaleReport,
1780
- chordScales,
1781
- chordToneRole,
1782
- createsHiddenParallelPerfect,
1783
- createsParallelOctave,
1784
- createsParallelPerfect,
1785
- createsParallelUnison,
1786
- createsVerticalDissonance,
1787
- createsVoiceCrossing,
1788
- createsVoiceOverlap,
1789
- diatonicPitchClasses,
1790
- diatonicSeventh,
1791
- diatonicTriad,
1792
- enumerateSafePitches,
1793
- evaluateSafety,
1794
- exceedsSpacing,
1795
- formatChordSymbol,
1796
- isForbiddenMelodicLeap,
1797
- isLeadingToneResolution,
1798
- isScaleTone,
1799
- majorKey,
1800
- makeChord,
1801
- maskFromOffsets,
1802
- minorKey,
1803
- nearestScaleTone,
1804
- nextVoicing,
1805
- noteNames,
1806
- parseChordSymbol,
1807
- pitchToScaleDegree,
1808
- roleOf,
1809
- scaleByName,
1810
- scaleMatchesChord,
1811
- scaleTonesInDegreeOrder,
1812
- scalesForChanges,
1813
- spellChord,
1814
- spellPitchClass,
1815
- spellPitchClasses,
1816
- spellScale,
1817
- transposeChordSymbol,
1818
- voiceChord,
1819
- voiceChordStyled,
1820
- voiceLeadingCost,
1821
- voiceProgression
1822
- });
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-T64C7ZD7.cjs');
2
+
3
+
4
+ var _chunkFCANXBATcjs = require('../chunk-FCANXBAT.cjs');
5
+
6
+
7
+
8
+
9
+
10
+ var _chunkQ6OP4U43cjs = require('../chunk-Q6OP4U43.cjs');
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+ var _chunkLW53AHQUcjs = require('../chunk-LW53AHQU.cjs');
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+ var _chunkFNDWXRRIcjs = require('../chunk-FNDWXRRI.cjs');
90
+ require('../chunk-7MGZ7D62.cjs');
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+ exports.ALTERED_MASK = _chunkFNDWXRRIcjs.ALTERED_MASK; exports.BLUES_MASK = _chunkFNDWXRRIcjs.BLUES_MASK; exports.CHROMATIC_MASK = _chunkFNDWXRRIcjs.CHROMATIC_MASK; exports.DORIAN_MASK = _chunkFNDWXRRIcjs.DORIAN_MASK; exports.HARMONIC_MINOR_MASK = _chunkFNDWXRRIcjs.HARMONIC_MINOR_MASK; exports.LOCRIAN_MASK = _chunkFNDWXRRIcjs.LOCRIAN_MASK; exports.LOCRIAN_NATURAL2_MASK = _chunkFNDWXRRIcjs.LOCRIAN_NATURAL2_MASK; exports.LYDIAN_DOMINANT_MASK = _chunkFNDWXRRIcjs.LYDIAN_DOMINANT_MASK; exports.LYDIAN_MASK = _chunkFNDWXRRIcjs.LYDIAN_MASK; exports.MAJOR_MASK = _chunkFNDWXRRIcjs.MAJOR_MASK; exports.MAJOR_PENTATONIC_MASK = _chunkFNDWXRRIcjs.MAJOR_PENTATONIC_MASK; exports.MELODIC_MINOR_MASK = _chunkFNDWXRRIcjs.MELODIC_MINOR_MASK; exports.MINOR_PENTATONIC_MASK = _chunkFNDWXRRIcjs.MINOR_PENTATONIC_MASK; exports.MIXOLYDIAN_B13_MASK = _chunkFNDWXRRIcjs.MIXOLYDIAN_B13_MASK; exports.MIXOLYDIAN_MASK = _chunkFNDWXRRIcjs.MIXOLYDIAN_MASK; exports.NAMED_SCALES = _chunkFNDWXRRIcjs.NAMED_SCALES; exports.NATURAL_MINOR_MASK = _chunkFNDWXRRIcjs.NATURAL_MINOR_MASK; exports.NoteSafety = _chunkQ6OP4U43cjs.NoteSafety; exports.OCTATONIC_HALF_WHOLE_MASK = _chunkFNDWXRRIcjs.OCTATONIC_HALF_WHOLE_MASK; exports.OCTATONIC_WHOLE_HALF_MASK = _chunkFNDWXRRIcjs.OCTATONIC_WHOLE_HALF_MASK; exports.PHRYGIAN_DOMINANT_MASK = _chunkFNDWXRRIcjs.PHRYGIAN_DOMINANT_MASK; exports.PHRYGIAN_MASK = _chunkFNDWXRRIcjs.PHRYGIAN_MASK; exports.ReasonFlag = _chunkQ6OP4U43cjs.ReasonFlag; exports.SATB_RANGES = _chunkLW53AHQUcjs.SATB_RANGES; exports.WHOLE_TONE_MASK = _chunkFNDWXRRIcjs.WHOLE_TONE_MASK; exports.availableTensions = _chunkLW53AHQUcjs.availableTensions; exports.avoidNotes = _chunkLW53AHQUcjs.avoidNotes; exports.chordFromDegree = _chunkFNDWXRRIcjs.chordFromDegree; exports.chordPitchClasses = _chunkFNDWXRRIcjs.chordPitchClasses; exports.chordQualities = _chunkFNDWXRRIcjs.chordQualities; exports.chordScaleReport = _chunkLW53AHQUcjs.chordScaleReport; exports.chordScales = _chunkLW53AHQUcjs.chordScales; exports.chordToneRole = _chunkFNDWXRRIcjs.chordToneRole; exports.createsHiddenParallelPerfect = _chunkFNDWXRRIcjs.createsHiddenParallelPerfect; exports.createsParallelOctave = _chunkFNDWXRRIcjs.createsParallelOctave; exports.createsParallelPerfect = _chunkFNDWXRRIcjs.createsParallelPerfect; exports.createsParallelUnison = _chunkFNDWXRRIcjs.createsParallelUnison; exports.createsVerticalDissonance = _chunkFNDWXRRIcjs.createsVerticalDissonance; exports.createsVoiceCrossing = _chunkFNDWXRRIcjs.createsVoiceCrossing; exports.createsVoiceOverlap = _chunkFNDWXRRIcjs.createsVoiceOverlap; exports.diatonicPitchClasses = _chunkFNDWXRRIcjs.diatonicPitchClasses; exports.diatonicSeventh = _chunkFNDWXRRIcjs.diatonicSeventh; exports.diatonicTriad = _chunkFNDWXRRIcjs.diatonicTriad; exports.enumerateSafePitches = _chunkQ6OP4U43cjs.enumerateSafePitches; exports.evaluateSafety = _chunkQ6OP4U43cjs.evaluateSafety; exports.exceedsSpacing = _chunkFNDWXRRIcjs.exceedsSpacing; exports.formatChordSymbol = _chunkLW53AHQUcjs.formatChordSymbol; exports.intervalAboveRoot = _chunkFNDWXRRIcjs.intervalAboveRoot; exports.isChordMember = _chunkFNDWXRRIcjs.isChordMember; exports.isForbiddenMelodicLeap = _chunkFNDWXRRIcjs.isForbiddenMelodicLeap; exports.isLeadingToneResolution = _chunkFNDWXRRIcjs.isLeadingToneResolution; exports.isScaleTone = _chunkFNDWXRRIcjs.isScaleTone; exports.majorKey = _chunkFNDWXRRIcjs.majorKey; exports.makeChord = _chunkFNDWXRRIcjs.makeChord; exports.maskFromOffsets = _chunkFNDWXRRIcjs.maskFromOffsets; exports.minorKey = _chunkFNDWXRRIcjs.minorKey; exports.namedScaleMask = _chunkFNDWXRRIcjs.namedScaleMask; exports.nearestScaleTone = _chunkFNDWXRRIcjs.nearestScaleTone; exports.nextVoicing = _chunkLW53AHQUcjs.nextVoicing; exports.noteNames = _chunkLW53AHQUcjs.noteNames; exports.parseChordSymbol = _chunkLW53AHQUcjs.parseChordSymbol; exports.pitchToScaleDegree = _chunkFNDWXRRIcjs.pitchToScaleDegree; exports.requireScaleMask = _chunkFNDWXRRIcjs.requireScaleMask; exports.roleOf = _chunkFCANXBATcjs.roleOf; exports.scaleByName = _chunkFNDWXRRIcjs.scaleByName; exports.scaleMatchesChord = _chunkLW53AHQUcjs.scaleMatchesChord; exports.scaleTonesInDegreeOrder = _chunkFNDWXRRIcjs.scaleTonesInDegreeOrder; exports.scalesForChanges = _chunkLW53AHQUcjs.scalesForChanges; exports.spellChord = _chunkLW53AHQUcjs.spellChord; exports.spellChordFromRoot = _chunkLW53AHQUcjs.spellChordFromRoot; exports.spellPitch = _chunkLW53AHQUcjs.spellPitch; exports.spellPitchClass = _chunkLW53AHQUcjs.spellPitchClass; exports.spellPitchClasses = _chunkLW53AHQUcjs.spellPitchClasses; exports.spellScale = _chunkLW53AHQUcjs.spellScale; exports.transposeChord = _chunkFNDWXRRIcjs.transposeChord; exports.transposeChordSymbol = _chunkLW53AHQUcjs.transposeChordSymbol; exports.voiceChord = _chunkLW53AHQUcjs.voiceChord; exports.voiceChordStyled = _chunkLW53AHQUcjs.voiceChordStyled; exports.voiceLeadingCost = _chunkLW53AHQUcjs.voiceLeadingCost; exports.voiceProgression = _chunkLW53AHQUcjs.voiceProgression;
1823
173
  //# sourceMappingURL=index.cjs.map