@libraz/libcantus 0.9.4 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -18
- package/README_ja.md +268 -0
- package/dist/analyze/index.cjs +7 -7
- package/dist/analyze/index.d.cts +9 -99
- package/dist/analyze/index.d.ts +9 -99
- package/dist/analyze/index.js +6 -6
- package/dist/{chunk-36N73KZ3.cjs → chunk-2A2QMA74.cjs} +80 -65
- package/dist/chunk-2A2QMA74.cjs.map +1 -0
- package/dist/{chunk-YLEMGEFH.js → chunk-2PTFGVD7.js} +50 -35
- package/dist/chunk-2PTFGVD7.js.map +1 -0
- package/dist/{chunk-ZEJR4TKL.cjs → chunk-357ZDPVU.cjs} +36 -47
- package/dist/chunk-357ZDPVU.cjs.map +1 -0
- package/dist/{chunk-EHVEBWM5.js → chunk-3KX76RLG.js} +136 -37
- package/dist/chunk-3KX76RLG.js.map +1 -0
- package/dist/{chunk-RC6GBMCD.cjs → chunk-4VZ5MZAM.cjs} +155 -111
- package/dist/chunk-4VZ5MZAM.cjs.map +1 -0
- package/dist/{chunk-RK35RIN7.js → chunk-7EONYVI5.js} +115 -28
- package/dist/chunk-7EONYVI5.js.map +1 -0
- package/dist/{chunk-GQSGS2N4.js → chunk-7JEP3MFY.js} +5 -16
- package/dist/chunk-7JEP3MFY.js.map +1 -0
- package/dist/{chunk-7NKDPF74.js → chunk-AID75RN3.js} +203 -104
- package/dist/chunk-AID75RN3.js.map +1 -0
- package/dist/{chunk-FNDWXRRI.cjs → chunk-BSLTLGM3.cjs} +55 -37
- package/dist/chunk-BSLTLGM3.cjs.map +1 -0
- package/dist/{chunk-NP4NA2FB.cjs → chunk-CU6VG2YM.cjs} +39 -36
- package/dist/chunk-CU6VG2YM.cjs.map +1 -0
- package/dist/{chunk-NYYWMV2C.js → chunk-DZMHIGI4.js} +27 -17
- package/dist/chunk-DZMHIGI4.js.map +1 -0
- package/dist/{chunk-I24MV65U.js → chunk-EDOTEABK.js} +18 -15
- package/dist/{chunk-I24MV65U.js.map → chunk-EDOTEABK.js.map} +1 -1
- package/dist/{chunk-NKIBQ6PT.js → chunk-HN2OEUN2.js} +7 -4
- package/dist/chunk-HN2OEUN2.js.map +1 -0
- package/dist/{chunk-D2FAJBYL.js → chunk-KBTTEX7Q.js} +30 -12
- package/dist/chunk-KBTTEX7Q.js.map +1 -0
- package/dist/{chunk-CAN76NCU.cjs → chunk-KQN2ZYND.cjs} +147 -102
- package/dist/chunk-KQN2ZYND.cjs.map +1 -0
- package/dist/{chunk-4HLLZPXT.cjs → chunk-MPTVJIVG.cjs} +350 -251
- package/dist/chunk-MPTVJIVG.cjs.map +1 -0
- package/dist/{chunk-RUMU3UA6.cjs → chunk-MTMZTMWM.cjs} +12 -12
- package/dist/{chunk-RUMU3UA6.cjs.map → chunk-MTMZTMWM.cjs.map} +1 -1
- package/dist/{chunk-KMHOICIY.js → chunk-NNB67XA2.js} +90 -45
- package/dist/chunk-NNB67XA2.js.map +1 -0
- package/dist/{chunk-LW53AHQU.cjs → chunk-OL3IHHSJ.cjs} +228 -141
- package/dist/chunk-OL3IHHSJ.cjs.map +1 -0
- package/dist/{chunk-7MGZ7D62.cjs → chunk-PI3UXRWK.cjs} +43 -13
- package/dist/chunk-PI3UXRWK.cjs.map +1 -0
- package/dist/{chunk-XEBG3G53.js → chunk-R2VVFAIN.js} +42 -12
- package/dist/chunk-R2VVFAIN.js.map +1 -0
- package/dist/{chunk-Q6OP4U43.cjs → chunk-WFDXOLUB.cjs} +50 -40
- package/dist/chunk-WFDXOLUB.cjs.map +1 -0
- package/dist/{chunk-NVE34YGZ.cjs → chunk-WTAN4ACG.cjs} +212 -113
- package/dist/chunk-WTAN4ACG.cjs.map +1 -0
- package/dist/{chunk-FCANXBAT.cjs → chunk-YFJXS3AU.cjs} +8 -5
- package/dist/chunk-YFJXS3AU.cjs.map +1 -0
- package/dist/{chunk-Q2XUP227.js → chunk-YUE6TJ4M.js} +89 -45
- package/dist/chunk-YUE6TJ4M.js.map +1 -0
- package/dist/{chunk-HKGYCQ34.js → chunk-ZGLJM4A4.js} +2 -2
- package/dist/core/index.cjs +15 -5
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +14 -4
- package/dist/core/index.d.ts +14 -4
- package/dist/core/index.js +14 -4
- package/dist/{function-DNugAOrt.d.cts → function-CxixTB02.d.cts} +98 -7
- package/dist/{function-BtiZb9i9.d.ts → function-DTCt675z.d.ts} +98 -7
- package/dist/generate/index.cjs +10 -10
- package/dist/generate/index.d.cts +21 -21
- package/dist/generate/index.d.ts +21 -21
- package/dist/generate/index.js +9 -9
- package/dist/{index-tJhkmQgE.d.cts → index-B2Ulxxpo.d.cts} +3 -2
- package/dist/{index-Be74mcon.d.cts → index-BkYJ0xMq.d.cts} +2 -2
- package/dist/{index-6VR8-kit.d.ts → index-BuaB-ypt.d.ts} +3 -2
- package/dist/{index-70p168VM.d.ts → index-CAN7v-kw.d.ts} +9 -2
- package/dist/{index-C83mZI1P.d.ts → index-COw1Ky9g.d.ts} +1 -1
- package/dist/{index-tSQh-xwY.d.ts → index-Cfx8xgH0.d.ts} +1 -1
- package/dist/{index-C5UBbQ4G.d.ts → index-DRtIhlJj.d.ts} +2 -2
- package/dist/{index-BtXT6UQ0.d.cts → index-alrRninU.d.cts} +9 -2
- package/dist/{index-y_ak9_Hi.d.cts → index-oTQbYYIs.d.cts} +1 -1
- package/dist/{index-OG65ocOr.d.ts → index-tR9jTn26.d.cts} +4 -1
- package/dist/{index-OG65ocOr.d.cts → index-tR9jTn26.d.ts} +4 -1
- package/dist/{index-D6b6na69.d.cts → index-x2vcsduE.d.cts} +1 -1
- package/dist/index.cjs +24 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +23 -13
- package/dist/model/index.cjs +7 -7
- package/dist/model/index.d.cts +48 -16
- package/dist/model/index.d.ts +48 -16
- package/dist/model/index.js +6 -6
- package/dist/{styled-DIRkk9Uz.d.ts → styled-Bl0ZK28h.d.ts} +40 -3
- package/dist/{styled-DJbkJQfj.d.cts → styled-Crv6SA4S.d.cts} +40 -3
- package/dist/theory/index.cjs +6 -6
- package/dist/theory/index.d.cts +9 -9
- package/dist/theory/index.d.ts +9 -9
- package/dist/theory/index.js +5 -5
- package/package.json +12 -9
- package/dist/chunk-36N73KZ3.cjs.map +0 -1
- package/dist/chunk-4HLLZPXT.cjs.map +0 -1
- package/dist/chunk-7MGZ7D62.cjs.map +0 -1
- package/dist/chunk-7NKDPF74.js.map +0 -1
- package/dist/chunk-CAN76NCU.cjs.map +0 -1
- package/dist/chunk-D2FAJBYL.js.map +0 -1
- package/dist/chunk-EHVEBWM5.js.map +0 -1
- package/dist/chunk-FCANXBAT.cjs.map +0 -1
- package/dist/chunk-FNDWXRRI.cjs.map +0 -1
- package/dist/chunk-GQSGS2N4.js.map +0 -1
- package/dist/chunk-KMHOICIY.js.map +0 -1
- package/dist/chunk-LW53AHQU.cjs.map +0 -1
- package/dist/chunk-NKIBQ6PT.js.map +0 -1
- package/dist/chunk-NP4NA2FB.cjs.map +0 -1
- package/dist/chunk-NVE34YGZ.cjs.map +0 -1
- package/dist/chunk-NYYWMV2C.js.map +0 -1
- package/dist/chunk-Q2XUP227.js.map +0 -1
- package/dist/chunk-Q6OP4U43.cjs.map +0 -1
- package/dist/chunk-RC6GBMCD.cjs.map +0 -1
- package/dist/chunk-RK35RIN7.js.map +0 -1
- package/dist/chunk-XEBG3G53.js.map +0 -1
- package/dist/chunk-YLEMGEFH.js.map +0 -1
- package/dist/chunk-ZEJR4TKL.cjs.map +0 -1
- /package/dist/{chunk-HKGYCQ34.js.map → chunk-ZGLJM4A4.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunk357ZDPVUcjs = require('./chunk-357ZDPVU.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
@@ -14,7 +14,7 @@ var _chunkZEJR4TKLcjs = require('./chunk-ZEJR4TKL.cjs');
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
var
|
|
17
|
+
var _chunkKQN2ZYNDcjs = require('./chunk-KQN2ZYND.cjs');
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
@@ -28,8 +28,8 @@ var _chunkCAN76NCUcjs = require('./chunk-CAN76NCU.cjs');
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
var _chunkLW53AHQUcjs = require('./chunk-LW53AHQU.cjs');
|
|
32
31
|
|
|
32
|
+
var _chunkOL3IHHSJcjs = require('./chunk-OL3IHHSJ.cjs');
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
|
|
@@ -41,8 +41,8 @@ var _chunkLW53AHQUcjs = require('./chunk-LW53AHQU.cjs');
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
var _chunkFNDWXRRIcjs = require('./chunk-FNDWXRRI.cjs');
|
|
45
44
|
|
|
45
|
+
var _chunkBSLTLGM3cjs = require('./chunk-BSLTLGM3.cjs');
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
|
|
@@ -57,7 +57,9 @@ var _chunkFNDWXRRIcjs = require('./chunk-FNDWXRRI.cjs');
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
var _chunkPI3UXRWKcjs = require('./chunk-PI3UXRWK.cjs');
|
|
61
63
|
|
|
62
64
|
// src/model/interval.ts
|
|
63
65
|
var INVERSION_SUM = 9;
|
|
@@ -77,10 +79,12 @@ var Interval = class _Interval {
|
|
|
77
79
|
#number;
|
|
78
80
|
#quality;
|
|
79
81
|
#semitones;
|
|
80
|
-
|
|
82
|
+
#descending;
|
|
83
|
+
constructor(numberValue, quality, semitones, descending = semitones < 0) {
|
|
81
84
|
this.#number = numberValue;
|
|
82
85
|
this.#quality = quality;
|
|
83
86
|
this.#semitones = semitones;
|
|
87
|
+
this.#descending = descending;
|
|
84
88
|
}
|
|
85
89
|
/**
|
|
86
90
|
* The spelled interval between two notes.
|
|
@@ -104,9 +108,9 @@ var Interval = class _Interval {
|
|
|
104
108
|
* `P5` spanning 8 semitones is not a value any other method can produce.
|
|
105
109
|
*/
|
|
106
110
|
static of(numberValue, quality, semitones) {
|
|
107
|
-
const expected =
|
|
111
|
+
const expected = _chunkPI3UXRWKcjs.intervalSemitones.call(void 0, numberValue, quality);
|
|
108
112
|
if (Math.abs(semitones) !== expected) {
|
|
109
|
-
throw new (0,
|
|
113
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(
|
|
110
114
|
`${quality}${numberValue} spans ${expected} semitones; received ${semitones}`
|
|
111
115
|
);
|
|
112
116
|
}
|
|
@@ -119,7 +123,12 @@ var Interval = class _Interval {
|
|
|
119
123
|
* @returns The wrapped interval.
|
|
120
124
|
*/
|
|
121
125
|
static fromData(data) {
|
|
122
|
-
return new _Interval(
|
|
126
|
+
return new _Interval(
|
|
127
|
+
data.number,
|
|
128
|
+
data.quality,
|
|
129
|
+
data.semitones,
|
|
130
|
+
_nullishCoalesce(data.descending, () => ( data.semitones < 0))
|
|
131
|
+
);
|
|
123
132
|
}
|
|
124
133
|
/**
|
|
125
134
|
* Rebuild an interval from its {@link Interval.toJSON} output.
|
|
@@ -138,7 +147,7 @@ var Interval = class _Interval {
|
|
|
138
147
|
* @throws If the name is not a quality label followed by a diatonic number.
|
|
139
148
|
*/
|
|
140
149
|
static parse(name) {
|
|
141
|
-
return _Interval.fromData(
|
|
150
|
+
return _Interval.fromData(_chunkPI3UXRWKcjs.parseInterval.call(void 0, name));
|
|
142
151
|
}
|
|
143
152
|
/** Diatonic size: 1 = unison, 2 = second, ... 8 = octave, and beyond. */
|
|
144
153
|
get number() {
|
|
@@ -166,10 +175,10 @@ var Interval = class _Interval {
|
|
|
166
175
|
* @returns The inverted interval, e.g. `M3` becomes `m6`.
|
|
167
176
|
*/
|
|
168
177
|
invert() {
|
|
169
|
-
const simple = (this.#number - 1) % 7 + 1;
|
|
178
|
+
const simple = this.#number === 8 ? 8 : (this.#number - 1) % 7 + 1;
|
|
170
179
|
const numberValue = INVERSION_SUM - simple;
|
|
171
180
|
const quality = invertQuality(this.#quality);
|
|
172
|
-
return _Interval.of(numberValue, quality,
|
|
181
|
+
return _Interval.of(numberValue, quality, _chunkPI3UXRWKcjs.intervalSemitones.call(void 0, numberValue, quality));
|
|
173
182
|
}
|
|
174
183
|
/**
|
|
175
184
|
* Whether the interval is consonant.
|
|
@@ -179,7 +188,7 @@ var Interval = class _Interval {
|
|
|
179
188
|
* @returns True if the interval is consonant in that context.
|
|
180
189
|
*/
|
|
181
190
|
isConsonant(twoVoice = true) {
|
|
182
|
-
return
|
|
191
|
+
return _chunkPI3UXRWKcjs.isConsonantInterval.call(void 0, this.#semitones, twoVoice);
|
|
183
192
|
}
|
|
184
193
|
/**
|
|
185
194
|
* Whether another interval is spelled identically.
|
|
@@ -191,7 +200,7 @@ var Interval = class _Interval {
|
|
|
191
200
|
* @returns True when number, quality, and span all match.
|
|
192
201
|
*/
|
|
193
202
|
equals(other) {
|
|
194
|
-
return this.#number === other.number && this.#quality === other.quality && this.#semitones === other.semitones;
|
|
203
|
+
return this.#number === other.number && this.#quality === other.quality && this.#semitones === other.semitones && this.#descending === other.#descending;
|
|
195
204
|
}
|
|
196
205
|
/**
|
|
197
206
|
* The plain interval data, for JSON serialization.
|
|
@@ -202,7 +211,17 @@ var Interval = class _Interval {
|
|
|
202
211
|
* @returns The diatonic number, quality, and semitone span.
|
|
203
212
|
*/
|
|
204
213
|
toJSON() {
|
|
205
|
-
return
|
|
214
|
+
return this.#descending ? {
|
|
215
|
+
number: this.#number,
|
|
216
|
+
quality: this.#quality,
|
|
217
|
+
semitones: this.#semitones,
|
|
218
|
+
descending: true
|
|
219
|
+
} : this.#semitones < 0 ? {
|
|
220
|
+
number: this.#number,
|
|
221
|
+
quality: this.#quality,
|
|
222
|
+
semitones: this.#semitones,
|
|
223
|
+
descending: false
|
|
224
|
+
} : { number: this.#number, quality: this.#quality, semitones: this.#semitones };
|
|
206
225
|
}
|
|
207
226
|
/**
|
|
208
227
|
* The interval's name, so a template literal or a log line reads as the
|
|
@@ -218,7 +237,7 @@ var Interval = class _Interval {
|
|
|
218
237
|
// src/model/note.ts
|
|
219
238
|
function copyNote(data) {
|
|
220
239
|
if (!Number.isInteger(data.letter) || data.letter < 0 || data.letter > 6) {
|
|
221
|
-
throw new (0,
|
|
240
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(
|
|
222
241
|
`note letter must be an integer in [0, 6]; received ${data.letter}`
|
|
223
242
|
);
|
|
224
243
|
}
|
|
@@ -226,6 +245,7 @@ function copyNote(data) {
|
|
|
226
245
|
if (data.octave !== void 0) {
|
|
227
246
|
copy.octave = data.octave;
|
|
228
247
|
}
|
|
248
|
+
_chunkPI3UXRWKcjs.noteToPitchClass.call(void 0, copy);
|
|
229
249
|
return copy;
|
|
230
250
|
}
|
|
231
251
|
var Note = class _Note {
|
|
@@ -247,7 +267,7 @@ var Note = class _Note {
|
|
|
247
267
|
* @throws If the text is not a valid note.
|
|
248
268
|
*/
|
|
249
269
|
static of(name) {
|
|
250
|
-
return new _Note(
|
|
270
|
+
return new _Note(_chunkPI3UXRWKcjs.parseNote.call(void 0, name));
|
|
251
271
|
}
|
|
252
272
|
/**
|
|
253
273
|
* Name a MIDI number (middle C = C4 = 60) as a note.
|
|
@@ -257,7 +277,7 @@ var Note = class _Note {
|
|
|
257
277
|
* @returns The spelled note, with octave.
|
|
258
278
|
*/
|
|
259
279
|
static fromMidi(midi, spelling = "sharp") {
|
|
260
|
-
return new _Note(
|
|
280
|
+
return new _Note(_chunkPI3UXRWKcjs.midiToNote.call(void 0, midi, spelling));
|
|
261
281
|
}
|
|
262
282
|
/**
|
|
263
283
|
* Wrap an existing plain note object.
|
|
@@ -271,11 +291,11 @@ var Note = class _Note {
|
|
|
271
291
|
}
|
|
272
292
|
/** The note rendered as scientific pitch notation, e.g. `'G4'` or `'Bb'`. */
|
|
273
293
|
get name() {
|
|
274
|
-
return
|
|
294
|
+
return _chunkPI3UXRWKcjs.formatNote.call(void 0, this.#data);
|
|
275
295
|
}
|
|
276
296
|
/** The pitch class (0..11), ignoring octave. */
|
|
277
297
|
get pitchClass() {
|
|
278
|
-
return
|
|
298
|
+
return _chunkPI3UXRWKcjs.noteToPitchClass.call(void 0, this.#data);
|
|
279
299
|
}
|
|
280
300
|
/**
|
|
281
301
|
* The MIDI number (middle C = C4 = 60).
|
|
@@ -284,9 +304,9 @@ var Note = class _Note {
|
|
|
284
304
|
*/
|
|
285
305
|
get midi() {
|
|
286
306
|
if (this.#data.octave === void 0) {
|
|
287
|
-
throw new (0,
|
|
307
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(`note ${this.name} has no octave, so it has no MIDI number`);
|
|
288
308
|
}
|
|
289
|
-
return
|
|
309
|
+
return _chunkPI3UXRWKcjs.noteToMidi.call(void 0, this.#data);
|
|
290
310
|
}
|
|
291
311
|
/** The diatonic letter number: 0..6 for C..B. */
|
|
292
312
|
get letter() {
|
|
@@ -328,7 +348,7 @@ var Note = class _Note {
|
|
|
328
348
|
if (semitones === 0 && _optionalChain([opts, 'optionalAccess', _ => _.spelling]) === void 0) {
|
|
329
349
|
return new _Note(this.#data);
|
|
330
350
|
}
|
|
331
|
-
return new _Note(
|
|
351
|
+
return new _Note(_chunkPI3UXRWKcjs.transposeNote.call(void 0, this.#data, semitones, opts));
|
|
332
352
|
}
|
|
333
353
|
/**
|
|
334
354
|
* The spelled interval from this note to another.
|
|
@@ -337,7 +357,7 @@ var Note = class _Note {
|
|
|
337
357
|
* @returns The interval, which {@link Interval.toJSON} unwraps to plain data.
|
|
338
358
|
*/
|
|
339
359
|
intervalTo(other) {
|
|
340
|
-
return Interval.fromData(
|
|
360
|
+
return Interval.fromData(_chunkPI3UXRWKcjs.spelledInterval.call(void 0, this.#data, other.data));
|
|
341
361
|
}
|
|
342
362
|
/**
|
|
343
363
|
* Transpose by a spelled interval, keeping the spelling the interval names.
|
|
@@ -355,7 +375,7 @@ var Note = class _Note {
|
|
|
355
375
|
* ```
|
|
356
376
|
*/
|
|
357
377
|
transposeBy(interval) {
|
|
358
|
-
return new _Note(
|
|
378
|
+
return new _Note(_chunkPI3UXRWKcjs.transposeByInterval.call(void 0, this.#data, interval.toJSON()));
|
|
359
379
|
}
|
|
360
380
|
/**
|
|
361
381
|
* Rebuild a note from its {@link Note.toJSON} output.
|
|
@@ -400,13 +420,13 @@ var Note = class _Note {
|
|
|
400
420
|
|
|
401
421
|
// src/model/shared.ts
|
|
402
422
|
function spellPitchClassBare(pc, spelling) {
|
|
403
|
-
const spelled =
|
|
423
|
+
const spelled = _chunkPI3UXRWKcjs.midiToNote.call(void 0, 60 + _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, pc), spelling);
|
|
404
424
|
return { letter: spelled.letter, alter: spelled.alter };
|
|
405
425
|
}
|
|
406
426
|
|
|
407
427
|
// src/model/key.ts
|
|
408
428
|
function accidentalLoad(tonic, scale) {
|
|
409
|
-
return
|
|
429
|
+
return _chunkOL3IHHSJcjs.spellScale.call(void 0, tonic, scale).reduce((sum, note) => sum + Math.abs(note.alter), 0);
|
|
410
430
|
}
|
|
411
431
|
function bestTonicForScale(rootPc, scale) {
|
|
412
432
|
const sharp = spellPitchClassBare(rootPc, "sharp");
|
|
@@ -419,21 +439,38 @@ function bestTonicForScale(rootPc, scale) {
|
|
|
419
439
|
var Key = class _Key {
|
|
420
440
|
#scale;
|
|
421
441
|
#tonic;
|
|
442
|
+
#variant;
|
|
422
443
|
/**
|
|
423
444
|
* Wrap a key/scale and its spelled tonic.
|
|
424
445
|
*
|
|
425
446
|
* @param scale The key/scale; its root is normalized to a pitch class.
|
|
426
447
|
* @param tonic The spelled tonic anchoring letter-name spelling.
|
|
448
|
+
* @param variant Optional detected scale form retained for display.
|
|
427
449
|
*/
|
|
428
|
-
constructor(scale, tonic) {
|
|
429
|
-
|
|
450
|
+
constructor(scale, tonic, variant) {
|
|
451
|
+
_chunkPI3UXRWKcjs.assertInteger.call(void 0, scale.rootPc, "scale.rootPc");
|
|
452
|
+
_chunkPI3UXRWKcjs.assertInteger.call(void 0, scale.modeMask12, "scale.modeMask12", 1, 4095);
|
|
453
|
+
if ((scale.modeMask12 & 1) === 0) {
|
|
454
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)("scale.modeMask12 must include the tonic (bit 0)");
|
|
455
|
+
}
|
|
456
|
+
const rootPc = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, scale.rootPc);
|
|
430
457
|
if (tonic.pitchClass !== rootPc) {
|
|
431
|
-
throw new (0,
|
|
458
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(
|
|
432
459
|
`tonic ${tonic.name} does not match the scale root pitch class ${rootPc}; pass a tonic that spells the scale root, or omit it to have one chosen`
|
|
433
460
|
);
|
|
434
461
|
}
|
|
435
462
|
this.#scale = { rootPc, modeMask12: scale.modeMask12 };
|
|
436
463
|
this.#tonic = tonic;
|
|
464
|
+
this.#variant = variant;
|
|
465
|
+
}
|
|
466
|
+
/** Preserve detection metadata while replacing its plain key with this API's Key. */
|
|
467
|
+
static #fromMatch(match) {
|
|
468
|
+
const key = new _Key(
|
|
469
|
+
match.key,
|
|
470
|
+
bestTonicForScale(_chunkPI3UXRWKcjs.pitchClassOf.call(void 0, match.key.rootPc), match.key),
|
|
471
|
+
match.variant
|
|
472
|
+
);
|
|
473
|
+
return { ...match, key };
|
|
437
474
|
}
|
|
438
475
|
/**
|
|
439
476
|
* A major key.
|
|
@@ -446,9 +483,9 @@ var Key = class _Key {
|
|
|
446
483
|
static major(root) {
|
|
447
484
|
if (typeof root === "string") {
|
|
448
485
|
const tonic = Note.of(root);
|
|
449
|
-
return new _Key(
|
|
486
|
+
return new _Key(_chunkBSLTLGM3cjs.majorKey.call(void 0, tonic.pitchClass), tonic);
|
|
450
487
|
}
|
|
451
|
-
const scale =
|
|
488
|
+
const scale = _chunkBSLTLGM3cjs.majorKey.call(void 0, root);
|
|
452
489
|
return new _Key(scale, bestTonicForScale(root, scale));
|
|
453
490
|
}
|
|
454
491
|
/**
|
|
@@ -462,9 +499,9 @@ var Key = class _Key {
|
|
|
462
499
|
static minor(root) {
|
|
463
500
|
if (typeof root === "string") {
|
|
464
501
|
const tonic = Note.of(root);
|
|
465
|
-
return new _Key(
|
|
502
|
+
return new _Key(_chunkBSLTLGM3cjs.minorKey.call(void 0, tonic.pitchClass), tonic);
|
|
466
503
|
}
|
|
467
|
-
const scale =
|
|
504
|
+
const scale = _chunkBSLTLGM3cjs.minorKey.call(void 0, root);
|
|
468
505
|
return new _Key(scale, bestTonicForScale(root, scale));
|
|
469
506
|
}
|
|
470
507
|
/**
|
|
@@ -480,10 +517,10 @@ var Key = class _Key {
|
|
|
480
517
|
static named(name, root) {
|
|
481
518
|
if (typeof root === "string") {
|
|
482
519
|
const tonic = Note.of(root);
|
|
483
|
-
return new _Key(
|
|
520
|
+
return new _Key(_chunkBSLTLGM3cjs.scaleByName.call(void 0, name, tonic.pitchClass), tonic);
|
|
484
521
|
}
|
|
485
|
-
const scale =
|
|
486
|
-
return new _Key(scale, bestTonicForScale(
|
|
522
|
+
const scale = _chunkBSLTLGM3cjs.scaleByName.call(void 0, name, _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, root));
|
|
523
|
+
return new _Key(scale, bestTonicForScale(_chunkPI3UXRWKcjs.pitchClassOf.call(void 0, root), scale));
|
|
487
524
|
}
|
|
488
525
|
/**
|
|
489
526
|
* Wrap an existing `KeyScale`, synthesizing a spelled tonic when none is
|
|
@@ -500,7 +537,7 @@ var Key = class _Key {
|
|
|
500
537
|
* @throws If the given tonic is not the scale's root pitch class.
|
|
501
538
|
*/
|
|
502
539
|
static of(scale, tonic) {
|
|
503
|
-
return new _Key(scale, _nullishCoalesce(tonic, () => ( bestTonicForScale(
|
|
540
|
+
return new _Key(scale, _nullishCoalesce(tonic, () => ( bestTonicForScale(_chunkPI3UXRWKcjs.pitchClassOf.call(void 0, scale.rootPc), scale))));
|
|
504
541
|
}
|
|
505
542
|
/**
|
|
506
543
|
* Rebuild a key from its {@link Key.toJSON} output.
|
|
@@ -521,7 +558,17 @@ var Key = class _Key {
|
|
|
521
558
|
* @returns Ranked keys (may be empty).
|
|
522
559
|
*/
|
|
523
560
|
static detect(pitches, opts) {
|
|
524
|
-
return
|
|
561
|
+
return _Key.detectMatches(pitches, opts).map((match) => match.key);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Identify keys while retaining each candidate's score, fit, and scale form.
|
|
565
|
+
*
|
|
566
|
+
* @param pitches MIDI pitches or bare pitch classes.
|
|
567
|
+
* @param opts How to weigh the input; see {@link DetectKeyOptions}.
|
|
568
|
+
* @returns Ranked key matches (may be empty).
|
|
569
|
+
*/
|
|
570
|
+
static detectMatches(pitches, opts) {
|
|
571
|
+
return _chunkKQN2ZYNDcjs.detectKey.call(void 0, pitches, opts).map((match) => _Key.#fromMatch(match));
|
|
525
572
|
}
|
|
526
573
|
/**
|
|
527
574
|
* The single best key interpretation of a pitch set.
|
|
@@ -536,8 +583,8 @@ var Key = class _Key {
|
|
|
536
583
|
* ```
|
|
537
584
|
*/
|
|
538
585
|
static detectBest(pitches, opts) {
|
|
539
|
-
const best =
|
|
540
|
-
return best === null ? null : _Key
|
|
586
|
+
const best = _chunkKQN2ZYNDcjs.detectKeyBest.call(void 0, pitches, opts);
|
|
587
|
+
return best === null ? null : _Key.#fromMatch(best).key;
|
|
541
588
|
}
|
|
542
589
|
/**
|
|
543
590
|
* Whether another key has the same tonic pitch class and mode.
|
|
@@ -566,7 +613,11 @@ var Key = class _Key {
|
|
|
566
613
|
}
|
|
567
614
|
/** Whether the scale has a minor third and no major third. */
|
|
568
615
|
get isMinor() {
|
|
569
|
-
return
|
|
616
|
+
return _chunkKQN2ZYNDcjs.isMinorKey.call(void 0, this.#scale);
|
|
617
|
+
}
|
|
618
|
+
/** The detected scale form, when this key came from key detection. */
|
|
619
|
+
get variant() {
|
|
620
|
+
return this.#variant;
|
|
570
621
|
}
|
|
571
622
|
/**
|
|
572
623
|
* The scale's pitch classes in ascending scale-degree order (degree 0 first).
|
|
@@ -574,7 +625,7 @@ var Key = class _Key {
|
|
|
574
625
|
* @returns One pitch class per scale degree.
|
|
575
626
|
*/
|
|
576
627
|
pitchClasses() {
|
|
577
|
-
return
|
|
628
|
+
return _chunkBSLTLGM3cjs.scaleTonesInDegreeOrder.call(void 0, this.#scale);
|
|
578
629
|
}
|
|
579
630
|
/**
|
|
580
631
|
* Transpose the key by a number of semitones.
|
|
@@ -592,9 +643,13 @@ var Key = class _Key {
|
|
|
592
643
|
* ```
|
|
593
644
|
*/
|
|
594
645
|
transpose(semitones) {
|
|
595
|
-
|
|
596
|
-
const rootPc =
|
|
597
|
-
return _Key
|
|
646
|
+
_chunkPI3UXRWKcjs.assertFiniteNumber.call(void 0, semitones, "semitones");
|
|
647
|
+
const rootPc = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, this.#scale.rootPc + Math.round(semitones));
|
|
648
|
+
return new _Key(
|
|
649
|
+
{ rootPc, modeMask12: this.#scale.modeMask12 },
|
|
650
|
+
this.#tonic.transpose(semitones),
|
|
651
|
+
this.#variant
|
|
652
|
+
);
|
|
598
653
|
}
|
|
599
654
|
/**
|
|
600
655
|
* The spelled scale, one note per degree (e.g. C D E F G A B for C major).
|
|
@@ -602,7 +657,7 @@ var Key = class _Key {
|
|
|
602
657
|
* @returns Spelled octave-less notes in scale-degree order.
|
|
603
658
|
*/
|
|
604
659
|
notes() {
|
|
605
|
-
return
|
|
660
|
+
return _chunkOL3IHHSJcjs.spellScale.call(void 0, this.#tonic.data, this.#scale).map((note) => new Note(note));
|
|
606
661
|
}
|
|
607
662
|
/**
|
|
608
663
|
* Alias of {@link Key.notes}.
|
|
@@ -636,7 +691,7 @@ var Key = class _Key {
|
|
|
636
691
|
* an explicit `quality` for those.
|
|
637
692
|
*/
|
|
638
693
|
chord(degree, quality) {
|
|
639
|
-
const data = quality === void 0 ?
|
|
694
|
+
const data = quality === void 0 ? _chunkBSLTLGM3cjs.diatonicTriad.call(void 0, degree, this.#scale) : _chunkBSLTLGM3cjs.chordFromDegree.call(void 0, degree, quality, this.#scale);
|
|
640
695
|
return new Chord(data, this);
|
|
641
696
|
}
|
|
642
697
|
/**
|
|
@@ -648,7 +703,7 @@ var Key = class _Key {
|
|
|
648
703
|
* degrees. Use {@link Key.chord} with an explicit quality instead.
|
|
649
704
|
*/
|
|
650
705
|
diatonicTriad(degree) {
|
|
651
|
-
return new Chord(
|
|
706
|
+
return new Chord(_chunkBSLTLGM3cjs.diatonicTriad.call(void 0, degree, this.#scale), this);
|
|
652
707
|
}
|
|
653
708
|
/**
|
|
654
709
|
* The diatonic seventh chord on a scale degree, carrying this key as context.
|
|
@@ -659,7 +714,7 @@ var Key = class _Key {
|
|
|
659
714
|
* degrees. Use {@link Key.chord} with an explicit quality instead.
|
|
660
715
|
*/
|
|
661
716
|
diatonicSeventh(degree) {
|
|
662
|
-
return new Chord(
|
|
717
|
+
return new Chord(_chunkBSLTLGM3cjs.diatonicSeventh.call(void 0, degree, this.#scale), this);
|
|
663
718
|
}
|
|
664
719
|
/**
|
|
665
720
|
* Build the chord denoted by a Roman numeral in this key (including applied
|
|
@@ -670,7 +725,7 @@ var Key = class _Key {
|
|
|
670
725
|
* @throws If the numeral is not valid.
|
|
671
726
|
*/
|
|
672
727
|
roman(text) {
|
|
673
|
-
return new Chord(
|
|
728
|
+
return new Chord(_chunkKQN2ZYNDcjs.romanToChord.call(void 0, text, this.#scale), this);
|
|
674
729
|
}
|
|
675
730
|
/**
|
|
676
731
|
* Whether a pitch belongs to the scale.
|
|
@@ -679,7 +734,7 @@ var Key = class _Key {
|
|
|
679
734
|
* @returns True if the pitch class is a scale tone.
|
|
680
735
|
*/
|
|
681
736
|
contains(x) {
|
|
682
|
-
return
|
|
737
|
+
return _chunkBSLTLGM3cjs.isScaleTone.call(void 0, typeof x === "number" ? x : x.pitchClass, this.#scale);
|
|
683
738
|
}
|
|
684
739
|
/**
|
|
685
740
|
* The plain key data, for JSON serialization.
|
|
@@ -696,12 +751,14 @@ var Key = class _Key {
|
|
|
696
751
|
}
|
|
697
752
|
/**
|
|
698
753
|
* The key's tonic and mode, so a template literal or a log line reads as the
|
|
699
|
-
* key.
|
|
700
|
-
* a scale name.
|
|
754
|
+
* key. Detected harmonic and melodic minor keys retain their scale form.
|
|
701
755
|
*
|
|
702
756
|
* @returns The name, e.g. `'C major'` or `'A minor'`.
|
|
703
757
|
*/
|
|
704
758
|
toString() {
|
|
759
|
+
if (this.#variant === "harmonic" || this.#variant === "melodic") {
|
|
760
|
+
return `${this.#tonic.name} ${this.#variant} minor`;
|
|
761
|
+
}
|
|
705
762
|
return `${this.#tonic.name} ${this.isMinor ? "minor" : "major"}`;
|
|
706
763
|
}
|
|
707
764
|
};
|
|
@@ -717,9 +774,13 @@ var Progression = class _Progression {
|
|
|
717
774
|
* @param key Optional key context for analysis methods.
|
|
718
775
|
*/
|
|
719
776
|
constructor(chords, key) {
|
|
720
|
-
this.#chords = Object.freeze(
|
|
777
|
+
this.#chords = Object.freeze(_Progression.#attachKey(chords, key));
|
|
721
778
|
this.#key = key;
|
|
722
779
|
}
|
|
780
|
+
/** Attach a progression key to chord members that do not already carry one. */
|
|
781
|
+
static #attachKey(chords, key) {
|
|
782
|
+
return key === void 0 ? [...chords] : chords.map((chord) => chord.key === void 0 ? chord.withKey(key) : chord);
|
|
783
|
+
}
|
|
723
784
|
/**
|
|
724
785
|
* Build a progression from the {@link ChordSpan} records the generators
|
|
725
786
|
* return, keeping their order.
|
|
@@ -740,11 +801,10 @@ var Progression = class _Progression {
|
|
|
740
801
|
* ```
|
|
741
802
|
*/
|
|
742
803
|
static fromSpans(spans, key) {
|
|
743
|
-
const chords = spans.map(
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
return key === void 0 ? new _Progression(chords) : new _Progression(chords, key);
|
|
804
|
+
const chords = spans.map(
|
|
805
|
+
(span) => Chord.from(_chunkBSLTLGM3cjs.makeChord.call(void 0, span.rootPc, span.quality, span.bassPc))
|
|
806
|
+
);
|
|
807
|
+
return new _Progression(chords, key);
|
|
748
808
|
}
|
|
749
809
|
/**
|
|
750
810
|
* Rebuild a progression from its {@link Progression.toJSON} output.
|
|
@@ -831,21 +891,23 @@ var Progression = class _Progression {
|
|
|
831
891
|
* @throws If any chord admits no voicing within the given ranges.
|
|
832
892
|
*/
|
|
833
893
|
voice(opts) {
|
|
834
|
-
|
|
894
|
+
const key = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _2 => _2.key]), () => ( _optionalChain([this, 'access', _3 => _3.#key, 'optionalAccess', _4 => _4.scale])));
|
|
895
|
+
return _chunkOL3IHHSJcjs.voiceProgression.call(void 0,
|
|
835
896
|
this.#chords.map((chord) => chord.data),
|
|
836
|
-
opts
|
|
897
|
+
key === void 0 ? opts : { ...opts, key }
|
|
837
898
|
);
|
|
838
899
|
}
|
|
839
900
|
/**
|
|
840
901
|
* The Roman numeral of each chord in a key.
|
|
841
902
|
*
|
|
842
903
|
* @param key Key to analyze in; falls back to the carried context.
|
|
904
|
+
* @param opts Applied-numeral rendering options.
|
|
843
905
|
* @returns One numeral per chord.
|
|
844
906
|
* @throws If no key is given and none is carried.
|
|
845
907
|
*/
|
|
846
|
-
roman(key) {
|
|
908
|
+
roman(key, opts) {
|
|
847
909
|
const resolved = this.#resolveKey(key);
|
|
848
|
-
return this.#chords.map((chord) => chord.roman(resolved));
|
|
910
|
+
return this.#chords.map((chord) => chord.roman(resolved, opts));
|
|
849
911
|
}
|
|
850
912
|
/**
|
|
851
913
|
* The harmonic function of each chord in a key.
|
|
@@ -865,17 +927,26 @@ var Progression = class _Progression {
|
|
|
865
927
|
* progression has fewer than two chords.
|
|
866
928
|
*
|
|
867
929
|
* @param key Key to analyze in; falls back to the carried context.
|
|
930
|
+
* @param opts Applied-numeral rendering options.
|
|
868
931
|
* @returns Per-chord analyses and the closing cadence.
|
|
869
932
|
* @throws If no key is given and none is carried.
|
|
870
933
|
*/
|
|
871
|
-
analyze(key) {
|
|
934
|
+
analyze(key, opts) {
|
|
872
935
|
const resolved = this.#resolveKey(key);
|
|
873
|
-
const chords = this.#chords.map((chord) => chord.analyze(resolved));
|
|
936
|
+
const chords = this.#chords.map((chord) => chord.analyze(resolved, opts));
|
|
874
937
|
const from = this.#chords[this.#chords.length - 2];
|
|
875
938
|
const to = this.#chords[this.#chords.length - 1];
|
|
876
|
-
const cadence = from !== void 0 && to !== void 0 ?
|
|
939
|
+
const cadence = from !== void 0 && to !== void 0 ? _chunkKQN2ZYNDcjs.detectCadence.call(void 0, from.data, to.data, resolved.scale) : null;
|
|
877
940
|
return { chords, cadence };
|
|
878
941
|
}
|
|
942
|
+
/**
|
|
943
|
+
* Choose one compatible scale for every chord, favoring smooth changes.
|
|
944
|
+
*
|
|
945
|
+
* @returns One scale choice per chord in this progression.
|
|
946
|
+
*/
|
|
947
|
+
scales() {
|
|
948
|
+
return _chunkOL3IHHSJcjs.scalesForChanges.call(void 0, this.#chords.map((chord) => chord.data));
|
|
949
|
+
}
|
|
879
950
|
/**
|
|
880
951
|
* The plain progression data, for JSON serialization.
|
|
881
952
|
*
|
|
@@ -900,12 +971,12 @@ var Progression = class _Progression {
|
|
|
900
971
|
* ```
|
|
901
972
|
*/
|
|
902
973
|
transpose(semitones) {
|
|
903
|
-
const key = _optionalChain([this, 'access',
|
|
974
|
+
const key = _optionalChain([this, 'access', _5 => _5.#key, 'optionalAccess', _6 => _6.transpose, 'call', _7 => _7(semitones)]);
|
|
904
975
|
const chords = this.#chords.map((chord) => {
|
|
905
976
|
const moved = chord.transpose(semitones);
|
|
906
977
|
return key !== void 0 && moved.key === void 0 ? moved.withKey(key) : moved;
|
|
907
978
|
});
|
|
908
|
-
return
|
|
979
|
+
return new _Progression(chords, key);
|
|
909
980
|
}
|
|
910
981
|
/**
|
|
911
982
|
* The chord symbols separated by spaces, so a template literal or a log line
|
|
@@ -916,17 +987,25 @@ var Progression = class _Progression {
|
|
|
916
987
|
toString() {
|
|
917
988
|
return this.#chords.map((chord) => chord.symbol()).join(" ");
|
|
918
989
|
}
|
|
990
|
+
/**
|
|
991
|
+
* The plain progression data, for JSON serialization.
|
|
992
|
+
*
|
|
993
|
+
* Private class fields do not serialize, so this preserves both the chord
|
|
994
|
+
* data and any carried key in `JSON.stringify(progression)`.
|
|
995
|
+
*
|
|
996
|
+
* @returns The chord data sequence and the carried key, if any.
|
|
997
|
+
*/
|
|
919
998
|
toJSON() {
|
|
920
999
|
return {
|
|
921
|
-
chords: this.#chords.map((chord) => chord.
|
|
922
|
-
key: _optionalChain([this, 'access',
|
|
1000
|
+
chords: this.#chords.map((chord) => chord.toJSON()),
|
|
1001
|
+
key: _optionalChain([this, 'access', _8 => _8.#key, 'optionalAccess', _9 => _9.toJSON, 'call', _10 => _10()])
|
|
923
1002
|
};
|
|
924
1003
|
}
|
|
925
1004
|
/** Resolve the key for an analysis method: explicit first, then carried. */
|
|
926
1005
|
#resolveKey(key) {
|
|
927
1006
|
const resolved = _nullishCoalesce(key, () => ( this.#key));
|
|
928
1007
|
if (resolved === void 0) {
|
|
929
|
-
throw new (0,
|
|
1008
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(
|
|
930
1009
|
"progression has no key context; pass a Key or attach one with withKey()"
|
|
931
1010
|
);
|
|
932
1011
|
}
|
|
@@ -936,7 +1015,14 @@ var Progression = class _Progression {
|
|
|
936
1015
|
|
|
937
1016
|
// src/model/chord.ts
|
|
938
1017
|
function hintMatches(hint, pc) {
|
|
939
|
-
return hint !== void 0 && pc !== void 0 &&
|
|
1018
|
+
return hint !== void 0 && pc !== void 0 && _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, _chunkPI3UXRWKcjs.noteToPitchClass.call(void 0, hint)) === _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, pc);
|
|
1019
|
+
}
|
|
1020
|
+
function transposeHint(hint, semitones) {
|
|
1021
|
+
if (hint === void 0) {
|
|
1022
|
+
return void 0;
|
|
1023
|
+
}
|
|
1024
|
+
const moved = _chunkPI3UXRWKcjs.transposeNote.call(void 0, hint, semitones);
|
|
1025
|
+
return { letter: moved.letter, alter: moved.alter };
|
|
940
1026
|
}
|
|
941
1027
|
function copyChord(data) {
|
|
942
1028
|
const copy = {
|
|
@@ -962,8 +1048,8 @@ function deriveBassSpelling(chord, key) {
|
|
|
962
1048
|
}
|
|
963
1049
|
const root = chord.rootSpelling;
|
|
964
1050
|
if (root !== void 0) {
|
|
965
|
-
const index = chord.intervals.findIndex((i) =>
|
|
966
|
-
const tone = index >= 0 ?
|
|
1051
|
+
const index = chord.intervals.findIndex((i) => _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, chord.rootPc + i) === bassPc);
|
|
1052
|
+
const tone = index >= 0 ? _chunkOL3IHHSJcjs.spellChordFromRoot.call(void 0, chord, root)[index] : void 0;
|
|
967
1053
|
if (tone !== void 0) {
|
|
968
1054
|
return { letter: tone.letter, alter: tone.alter };
|
|
969
1055
|
}
|
|
@@ -971,7 +1057,7 @@ function deriveBassSpelling(chord, key) {
|
|
|
971
1057
|
if (key === void 0) {
|
|
972
1058
|
return void 0;
|
|
973
1059
|
}
|
|
974
|
-
const spelled =
|
|
1060
|
+
const spelled = _chunkOL3IHHSJcjs.spellPitchClass.call(void 0, bassPc, key.tonic.data, key.scale);
|
|
975
1061
|
return { letter: spelled.letter, alter: spelled.alter };
|
|
976
1062
|
}
|
|
977
1063
|
var Chord = class _Chord {
|
|
@@ -996,10 +1082,13 @@ var Chord = class _Chord {
|
|
|
996
1082
|
* first key's letters forever. A spelling the caller supplied always wins.
|
|
997
1083
|
*/
|
|
998
1084
|
get #data() {
|
|
1085
|
+
return this.#dataWithKey(this.#key);
|
|
1086
|
+
}
|
|
1087
|
+
/** Build a read view whose missing spellings are derived from `key`. */
|
|
1088
|
+
#dataWithKey(key) {
|
|
999
1089
|
const out = copyChord(this.#given);
|
|
1000
|
-
const key = this.#key;
|
|
1001
1090
|
if (out.rootSpelling === void 0 && key !== void 0) {
|
|
1002
|
-
out.rootSpelling =
|
|
1091
|
+
out.rootSpelling = _chunkOL3IHHSJcjs.spellPitchClass.call(void 0, out.rootPc, key.tonic.data, key.scale);
|
|
1003
1092
|
}
|
|
1004
1093
|
if (out.bassSpelling === void 0) {
|
|
1005
1094
|
const bass = deriveBassSpelling(out, key);
|
|
@@ -1022,7 +1111,7 @@ var Chord = class _Chord {
|
|
|
1022
1111
|
const bassNote = typeof bass === "string" ? Note.of(bass) : void 0;
|
|
1023
1112
|
const bassPc = bassNote !== void 0 ? bassNote.pitchClass : bass;
|
|
1024
1113
|
const rootNote = typeof root === "string" ? Note.of(root) : void 0;
|
|
1025
|
-
const data =
|
|
1114
|
+
const data = _chunkBSLTLGM3cjs.makeChord.call(void 0,
|
|
1026
1115
|
rootNote !== void 0 ? rootNote.pitchClass : root,
|
|
1027
1116
|
quality,
|
|
1028
1117
|
bassPc
|
|
@@ -1074,7 +1163,7 @@ var Chord = class _Chord {
|
|
|
1074
1163
|
* @throws If the root or quality is not recognized.
|
|
1075
1164
|
*/
|
|
1076
1165
|
static parse(symbol) {
|
|
1077
|
-
return new _Chord(
|
|
1166
|
+
return new _Chord(_chunkOL3IHHSJcjs.parseChordSymbol.call(void 0, symbol));
|
|
1078
1167
|
}
|
|
1079
1168
|
/**
|
|
1080
1169
|
* Identify the chords matching a set of pitches, best interpretation first.
|
|
@@ -1084,8 +1173,8 @@ var Chord = class _Chord {
|
|
|
1084
1173
|
* @returns Ranked chord interpretations (may be empty).
|
|
1085
1174
|
*/
|
|
1086
1175
|
static detect(pitches, opts) {
|
|
1087
|
-
return
|
|
1088
|
-
(match) => new _Chord(
|
|
1176
|
+
return _chunkKQN2ZYNDcjs.detectChord.call(void 0, pitches, opts).map(
|
|
1177
|
+
(match) => new _Chord(_chunkBSLTLGM3cjs.makeChord.call(void 0, match.rootPc, match.quality, match.bassPc))
|
|
1089
1178
|
);
|
|
1090
1179
|
}
|
|
1091
1180
|
/**
|
|
@@ -1107,8 +1196,8 @@ var Chord = class _Chord {
|
|
|
1107
1196
|
* ```
|
|
1108
1197
|
*/
|
|
1109
1198
|
static detectMatches(pitches, opts) {
|
|
1110
|
-
return
|
|
1111
|
-
chord: new _Chord(
|
|
1199
|
+
return _chunkKQN2ZYNDcjs.detectChord.call(void 0, pitches, opts).map((match) => ({
|
|
1200
|
+
chord: new _Chord(_chunkBSLTLGM3cjs.makeChord.call(void 0, match.rootPc, match.quality, match.bassPc)),
|
|
1112
1201
|
match
|
|
1113
1202
|
}));
|
|
1114
1203
|
}
|
|
@@ -1120,7 +1209,7 @@ var Chord = class _Chord {
|
|
|
1120
1209
|
* @returns The top-ranked chord, or null when nothing matches.
|
|
1121
1210
|
*/
|
|
1122
1211
|
static detectBest(pitches, opts) {
|
|
1123
|
-
const best =
|
|
1212
|
+
const best = _chunkKQN2ZYNDcjs.detectChordBest.call(void 0, pitches, opts);
|
|
1124
1213
|
return best === null ? null : new _Chord(best);
|
|
1125
1214
|
}
|
|
1126
1215
|
/** The root pitch class (0..11). */
|
|
@@ -1171,17 +1260,18 @@ var Chord = class _Chord {
|
|
|
1171
1260
|
* @returns Pitch classes ascending in [0, 11].
|
|
1172
1261
|
*/
|
|
1173
1262
|
pitchClasses() {
|
|
1174
|
-
return
|
|
1263
|
+
return _chunkBSLTLGM3cjs.chordPitchClasses.call(void 0, this.#data);
|
|
1175
1264
|
}
|
|
1176
1265
|
/**
|
|
1177
1266
|
* The chord's Roman numeral in a key.
|
|
1178
1267
|
*
|
|
1179
1268
|
* @param key Key to analyze in; falls back to the carried context.
|
|
1269
|
+
* @param opts Applied-numeral rendering options.
|
|
1180
1270
|
* @returns The Roman numeral string.
|
|
1181
1271
|
* @throws If no key is given and none is carried.
|
|
1182
1272
|
*/
|
|
1183
|
-
roman(key) {
|
|
1184
|
-
return
|
|
1273
|
+
roman(key, opts) {
|
|
1274
|
+
return _chunkKQN2ZYNDcjs.chordToRoman.call(void 0, this.#data, this.#resolveKey(key).scale, opts);
|
|
1185
1275
|
}
|
|
1186
1276
|
/**
|
|
1187
1277
|
* The chord's harmonic function (tonic / subdominant / dominant) in a key.
|
|
@@ -1191,17 +1281,18 @@ var Chord = class _Chord {
|
|
|
1191
1281
|
* @throws If no key is given and none is carried.
|
|
1192
1282
|
*/
|
|
1193
1283
|
function(key) {
|
|
1194
|
-
return
|
|
1284
|
+
return _chunkKQN2ZYNDcjs.functionOf.call(void 0, this.#data, this.#resolveKey(key).scale);
|
|
1195
1285
|
}
|
|
1196
1286
|
/**
|
|
1197
1287
|
* Full functional analysis: function, borrowing, and Roman numeral.
|
|
1198
1288
|
*
|
|
1199
1289
|
* @param key Key to analyze in; falls back to the carried context.
|
|
1290
|
+
* @param opts Applied-numeral rendering options.
|
|
1200
1291
|
* @returns The chord analysis.
|
|
1201
1292
|
* @throws If no key is given and none is carried.
|
|
1202
1293
|
*/
|
|
1203
|
-
analyze(key) {
|
|
1204
|
-
return
|
|
1294
|
+
analyze(key, opts) {
|
|
1295
|
+
return _chunkKQN2ZYNDcjs.analyzeChord.call(void 0, this.#data, this.#resolveKey(key).scale, opts);
|
|
1205
1296
|
}
|
|
1206
1297
|
/**
|
|
1207
1298
|
* Whether the chord is borrowed from the parallel mode (modal interchange).
|
|
@@ -1211,7 +1302,7 @@ var Chord = class _Chord {
|
|
|
1211
1302
|
* @throws If no key is given and none is carried.
|
|
1212
1303
|
*/
|
|
1213
1304
|
isBorrowed(key) {
|
|
1214
|
-
return
|
|
1305
|
+
return _chunkKQN2ZYNDcjs.isBorrowedChord.call(void 0, this.#data, this.#resolveKey(key).scale);
|
|
1215
1306
|
}
|
|
1216
1307
|
/**
|
|
1217
1308
|
* The origin of a non-diatonic chord (parallel mode or Neapolitan), or null.
|
|
@@ -1221,7 +1312,7 @@ var Chord = class _Chord {
|
|
|
1221
1312
|
* @throws If no key is given and none is carried.
|
|
1222
1313
|
*/
|
|
1223
1314
|
borrowedSource(key) {
|
|
1224
|
-
return
|
|
1315
|
+
return _chunkKQN2ZYNDcjs.borrowedSource.call(void 0, this.#data, this.#resolveKey(key).scale);
|
|
1225
1316
|
}
|
|
1226
1317
|
/**
|
|
1227
1318
|
* The chord rendered as a lead-sheet symbol (e.g. `'Cmaj7'`, `'F#m7'`, `'C/G'`).
|
|
@@ -1230,7 +1321,7 @@ var Chord = class _Chord {
|
|
|
1230
1321
|
* @returns The chord symbol.
|
|
1231
1322
|
*/
|
|
1232
1323
|
symbol(opts) {
|
|
1233
|
-
return
|
|
1324
|
+
return _chunkOL3IHHSJcjs.formatChordSymbol.call(void 0, this.#data, opts);
|
|
1234
1325
|
}
|
|
1235
1326
|
/**
|
|
1236
1327
|
* Realize the chord as one MIDI pitch per voice, ascending.
|
|
@@ -1243,8 +1334,8 @@ var Chord = class _Chord {
|
|
|
1243
1334
|
* @throws If no voicing fits the given ranges.
|
|
1244
1335
|
*/
|
|
1245
1336
|
voice(opts) {
|
|
1246
|
-
const key = _nullishCoalesce(_optionalChain([opts, 'optionalAccess',
|
|
1247
|
-
return
|
|
1337
|
+
const key = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _11 => _11.key]), () => ( _optionalChain([this, 'access', _12 => _12.#key, 'optionalAccess', _13 => _13.scale])));
|
|
1338
|
+
return _chunkOL3IHHSJcjs.voiceChord.call(void 0, this.#data, key === void 0 ? opts : { ...opts, key });
|
|
1248
1339
|
}
|
|
1249
1340
|
/**
|
|
1250
1341
|
* Realize the chord as a single styled voicing (`close`, `drop2`, `drop3`,
|
|
@@ -1254,7 +1345,7 @@ var Chord = class _Chord {
|
|
|
1254
1345
|
* @returns MIDI pitches, ascending.
|
|
1255
1346
|
*/
|
|
1256
1347
|
styledVoicing(opts) {
|
|
1257
|
-
return
|
|
1348
|
+
return _chunkOL3IHHSJcjs.voiceChordStyled.call(void 0, this.#data, opts);
|
|
1258
1349
|
}
|
|
1259
1350
|
/**
|
|
1260
1351
|
* The negative-harmony mirror of the chord about the key's tonic–dominant
|
|
@@ -1267,7 +1358,7 @@ var Chord = class _Chord {
|
|
|
1267
1358
|
*/
|
|
1268
1359
|
negativeHarmony(key) {
|
|
1269
1360
|
const resolved = this.#resolveKey(key);
|
|
1270
|
-
return new _Chord(
|
|
1361
|
+
return new _Chord(_chunk357ZDPVUcjs.negativeHarmonyMirror.call(void 0, this.#data, resolved.scale), _nullishCoalesce(key, () => ( this.#key)));
|
|
1271
1362
|
}
|
|
1272
1363
|
/**
|
|
1273
1364
|
* The n-th inversion: a copy whose bass is the chord tone `n` steps above the
|
|
@@ -1286,14 +1377,14 @@ var Chord = class _Chord {
|
|
|
1286
1377
|
const intervals = data.intervals;
|
|
1287
1378
|
const length = intervals.length;
|
|
1288
1379
|
if (length === 0) {
|
|
1289
|
-
throw new (0,
|
|
1380
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)("cannot invert a chord with no intervals");
|
|
1290
1381
|
}
|
|
1291
1382
|
const index = (n % length + length) % length;
|
|
1292
1383
|
delete data.bassSpelling;
|
|
1293
1384
|
if (index === 0) {
|
|
1294
1385
|
delete data.bassPc;
|
|
1295
1386
|
} else {
|
|
1296
|
-
data.bassPc =
|
|
1387
|
+
data.bassPc = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, data.rootPc + (_nullishCoalesce(intervals[index], () => ( 0))));
|
|
1297
1388
|
}
|
|
1298
1389
|
return new _Chord(data, this.#key);
|
|
1299
1390
|
}
|
|
@@ -1314,8 +1405,16 @@ var Chord = class _Chord {
|
|
|
1314
1405
|
* ```
|
|
1315
1406
|
*/
|
|
1316
1407
|
transpose(semitones) {
|
|
1317
|
-
const moved =
|
|
1318
|
-
|
|
1408
|
+
const moved = _chunkBSLTLGM3cjs.transposeChord.call(void 0, this.#given, semitones);
|
|
1409
|
+
const rootSpelling = transposeHint(this.#given.rootSpelling, semitones);
|
|
1410
|
+
const bassSpelling = transposeHint(this.#given.bassSpelling, semitones);
|
|
1411
|
+
if (rootSpelling !== void 0) {
|
|
1412
|
+
moved.rootSpelling = rootSpelling;
|
|
1413
|
+
}
|
|
1414
|
+
if (bassSpelling !== void 0) {
|
|
1415
|
+
moved.bassSpelling = bassSpelling;
|
|
1416
|
+
}
|
|
1417
|
+
return new _Chord(moved, _optionalChain([this, 'access', _14 => _14.#key, 'optionalAccess', _15 => _15.transpose, 'call', _16 => _16(semitones)]));
|
|
1319
1418
|
}
|
|
1320
1419
|
/**
|
|
1321
1420
|
* The named scales that fit over this chord, best fit first, rooted on the
|
|
@@ -1324,7 +1423,7 @@ var Chord = class _Chord {
|
|
|
1324
1423
|
* @returns The matching scales.
|
|
1325
1424
|
*/
|
|
1326
1425
|
scales() {
|
|
1327
|
-
return
|
|
1426
|
+
return _chunkOL3IHHSJcjs.chordScales.call(void 0, this.#data);
|
|
1328
1427
|
}
|
|
1329
1428
|
/**
|
|
1330
1429
|
* The available tensions (usable non-chord, non-avoid scale tones) of a
|
|
@@ -1335,7 +1434,7 @@ var Chord = class _Chord {
|
|
|
1335
1434
|
* @throws If `scaleName` is not a built-in scale.
|
|
1336
1435
|
*/
|
|
1337
1436
|
tensions(scaleName) {
|
|
1338
|
-
return
|
|
1437
|
+
return _chunkOL3IHHSJcjs.availableTensions.call(void 0, this.#data, scaleName);
|
|
1339
1438
|
}
|
|
1340
1439
|
/**
|
|
1341
1440
|
* The avoid notes (scale tones a semitone above a chord tone) of a scale
|
|
@@ -1346,7 +1445,7 @@ var Chord = class _Chord {
|
|
|
1346
1445
|
* @throws If `scaleName` is not a built-in scale.
|
|
1347
1446
|
*/
|
|
1348
1447
|
avoidNotes(scaleName) {
|
|
1349
|
-
return
|
|
1448
|
+
return _chunkOL3IHHSJcjs.avoidNotes.call(void 0, this.#data, scaleName);
|
|
1350
1449
|
}
|
|
1351
1450
|
/**
|
|
1352
1451
|
* Spell the chord tones with letter names, root first, in the key's spelling.
|
|
@@ -1368,23 +1467,23 @@ var Chord = class _Chord {
|
|
|
1368
1467
|
* spelling of its own.
|
|
1369
1468
|
*/
|
|
1370
1469
|
spell(key) {
|
|
1371
|
-
const data = this.#data;
|
|
1372
1470
|
const resolved = _nullishCoalesce(key, () => ( this.#key));
|
|
1471
|
+
const data = this.#dataWithKey(resolved);
|
|
1373
1472
|
let tones;
|
|
1374
1473
|
if (resolved === void 0) {
|
|
1375
1474
|
const root = data.rootSpelling;
|
|
1376
1475
|
if (root === void 0) {
|
|
1377
|
-
throw new (0,
|
|
1476
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(
|
|
1378
1477
|
"chord has no key context and no root spelling; pass a Key, attach one with withKey(), or build the chord from a symbol"
|
|
1379
1478
|
);
|
|
1380
1479
|
}
|
|
1381
|
-
tones =
|
|
1480
|
+
tones = _chunkOL3IHHSJcjs.spellChordFromRoot.call(void 0, data, root);
|
|
1382
1481
|
} else {
|
|
1383
|
-
tones =
|
|
1482
|
+
tones = _chunkOL3IHHSJcjs.spellChord.call(void 0, data, resolved.tonic.data, resolved.scale);
|
|
1384
1483
|
}
|
|
1385
1484
|
const bassPc = data.bassPc;
|
|
1386
1485
|
const bass = data.bassSpelling;
|
|
1387
|
-
if (bassPc !== void 0 && bass !== void 0 && !tones.some((tone) =>
|
|
1486
|
+
if (bassPc !== void 0 && bass !== void 0 && !tones.some((tone) => _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, _chunkPI3UXRWKcjs.noteToPitchClass.call(void 0, tone)) === _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, bassPc))) {
|
|
1388
1487
|
tones = [...tones, { letter: bass.letter, alter: bass.alter }];
|
|
1389
1488
|
}
|
|
1390
1489
|
return tones.map((note) => new Note(note));
|
|
@@ -1417,7 +1516,7 @@ var Chord = class _Chord {
|
|
|
1417
1516
|
* @returns A copy of the underlying plain chord object.
|
|
1418
1517
|
*/
|
|
1419
1518
|
toJSON() {
|
|
1420
|
-
return this
|
|
1519
|
+
return copyChord(this.#given);
|
|
1421
1520
|
}
|
|
1422
1521
|
/**
|
|
1423
1522
|
* The chord symbol, so a template literal or a log line reads as the chord.
|
|
@@ -1431,7 +1530,7 @@ var Chord = class _Chord {
|
|
|
1431
1530
|
#resolveKey(key) {
|
|
1432
1531
|
const resolved = _nullishCoalesce(key, () => ( this.#key));
|
|
1433
1532
|
if (resolved === void 0) {
|
|
1434
|
-
throw new (0,
|
|
1533
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(
|
|
1435
1534
|
"chord has no key context; pass a Key or attach one with withKey()"
|
|
1436
1535
|
);
|
|
1437
1536
|
}
|
|
@@ -1446,4 +1545,4 @@ var Chord = class _Chord {
|
|
|
1446
1545
|
|
|
1447
1546
|
|
|
1448
1547
|
exports.Interval = Interval; exports.Note = Note; exports.Key = Key; exports.Progression = Progression; exports.Chord = Chord;
|
|
1449
|
-
//# sourceMappingURL=chunk-
|
|
1548
|
+
//# sourceMappingURL=chunk-WTAN4ACG.cjs.map
|