@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
|
@@ -9,49 +9,54 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
var
|
|
12
|
+
var _chunkBSLTLGM3cjs = require('./chunk-BSLTLGM3.cjs');
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
var _chunkPI3UXRWKcjs = require('./chunk-PI3UXRWK.cjs');
|
|
20
22
|
|
|
21
23
|
// src/analyze/detect/index.ts
|
|
22
24
|
function uniquePitchClasses(pitches) {
|
|
23
|
-
return [...new Set(pitches.map(
|
|
25
|
+
return [...new Set(pitches.map(_chunkPI3UXRWKcjs.pitchClassOf))].sort((a, b) => a - b);
|
|
24
26
|
}
|
|
25
|
-
function assertPitches(pitches) {
|
|
26
|
-
|
|
27
|
+
function assertPitches(pitches, name, budget = void 0) {
|
|
28
|
+
_chunkPI3UXRWKcjs.assertGenerationBudget.call(void 0, pitches.length, name, budget);
|
|
27
29
|
for (let index = 0; index < pitches.length; index += 1) {
|
|
28
|
-
|
|
30
|
+
_chunkPI3UXRWKcjs.assertMidiPitch.call(void 0, _nullishCoalesce(pitches[index], () => ( Number.NaN)), `pitches[${index}]`);
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
function detectChord(pitches, opts = {}) {
|
|
32
|
-
assertPitches(pitches);
|
|
33
|
-
if (opts.bassPc !== void 0)
|
|
34
|
+
assertPitches(pitches, "chord detection pitches");
|
|
35
|
+
if (opts.bassPc !== void 0) _chunkPI3UXRWKcjs.assertFiniteNumber.call(void 0, opts.bassPc, "bassPc");
|
|
34
36
|
const input = uniquePitchClasses(pitches);
|
|
35
37
|
if (input.length === 0) {
|
|
36
38
|
return [];
|
|
37
39
|
}
|
|
38
40
|
const inputKind = opts.input === void 0 || opts.input === "auto" ? pitches.every((pitch) => Number.isInteger(pitch) && pitch >= 0 && pitch <= 11) ? "pitchClass" : "midi" : opts.input;
|
|
39
|
-
const bassPc = opts.bassPc !== void 0 ?
|
|
41
|
+
const bassPc = opts.bassPc !== void 0 ? _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, opts.bassPc) : inputKind === "midi" ? _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, pitches.reduce((lowest, pitch) => Math.min(lowest, pitch), Infinity)) : void 0;
|
|
40
42
|
const inputSet = new Set(input);
|
|
41
43
|
const matches = [];
|
|
42
|
-
const qualities =
|
|
44
|
+
const qualities = _chunkBSLTLGM3cjs.chordQualities.call(void 0, );
|
|
45
|
+
const toneCounts = new Map(
|
|
46
|
+
qualities.map((quality) => [quality, _chunkBSLTLGM3cjs.chordPitchClasses.call(void 0, _chunkBSLTLGM3cjs.makeChord.call(void 0, 0, quality)).length])
|
|
47
|
+
);
|
|
43
48
|
for (const rootPc of input) {
|
|
44
49
|
for (const quality of qualities) {
|
|
45
|
-
const chord =
|
|
46
|
-
const tones =
|
|
50
|
+
const chord = _chunkBSLTLGM3cjs.makeChord.call(void 0, rootPc, quality);
|
|
51
|
+
const tones = _chunkBSLTLGM3cjs.chordPitchClasses.call(void 0, chord);
|
|
47
52
|
const toneSet = new Set(tones);
|
|
48
53
|
const missingPcs = tones.filter((pc) => !inputSet.has(pc));
|
|
49
|
-
const fifthPc =
|
|
54
|
+
const fifthPc = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, rootPc + 7);
|
|
50
55
|
if (missingPcs.length > 1 || missingPcs.length === 1 && missingPcs[0] !== fifthPc) {
|
|
51
56
|
continue;
|
|
52
57
|
}
|
|
53
58
|
const extraPcs = input.filter((pc) => !toneSet.has(pc));
|
|
54
|
-
const bassIndex = bassPc === void 0 ? -1 : chord.intervals.findIndex((iv) =>
|
|
59
|
+
const bassIndex = bassPc === void 0 ? -1 : chord.intervals.findIndex((iv) => _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, rootPc + iv) === bassPc);
|
|
55
60
|
const inversion = bassPc === void 0 || bassIndex < 0 ? null : bassIndex;
|
|
56
61
|
const match = {
|
|
57
62
|
rootPc,
|
|
@@ -77,8 +82,8 @@ function detectChord(pitches, opts = {}) {
|
|
|
77
82
|
if (a.inversion === 0 !== (b.inversion === 0)) {
|
|
78
83
|
return a.inversion === 0 ? -1 : 1;
|
|
79
84
|
}
|
|
80
|
-
const aSize =
|
|
81
|
-
const bSize =
|
|
85
|
+
const aSize = _nullishCoalesce(toneCounts.get(a.quality), () => ( 0));
|
|
86
|
+
const bSize = _nullishCoalesce(toneCounts.get(b.quality), () => ( 0));
|
|
82
87
|
return bSize - aSize;
|
|
83
88
|
});
|
|
84
89
|
return matches;
|
|
@@ -88,39 +93,36 @@ function detectChordBest(pitches, opts = {}) {
|
|
|
88
93
|
if (!best) {
|
|
89
94
|
return null;
|
|
90
95
|
}
|
|
91
|
-
return
|
|
96
|
+
return _chunkBSLTLGM3cjs.makeChord.call(void 0, best.rootPc, best.quality, best.bassPc);
|
|
92
97
|
}
|
|
93
98
|
var MINOR_VARIANTS = [
|
|
94
|
-
{ variant: "natural", mask:
|
|
95
|
-
{ variant: "harmonic", mask:
|
|
96
|
-
{ variant: "melodic", mask:
|
|
99
|
+
{ variant: "natural", mask: _chunkBSLTLGM3cjs.NATURAL_MINOR_MASK },
|
|
100
|
+
{ variant: "harmonic", mask: _chunkBSLTLGM3cjs.HARMONIC_MINOR_MASK },
|
|
101
|
+
{ variant: "melodic", mask: _chunkBSLTLGM3cjs.MELODIC_MINOR_MASK }
|
|
97
102
|
];
|
|
98
|
-
var MAJOR_VARIANTS = [{ variant: "major", mask:
|
|
103
|
+
var MAJOR_VARIANTS = [{ variant: "major", mask: _chunkBSLTLGM3cjs.MAJOR_MASK }];
|
|
99
104
|
function detectKey(pitches, opts = {}) {
|
|
100
|
-
assertPitches(pitches);
|
|
101
|
-
const input = uniquePitchClasses(pitches);
|
|
102
|
-
if (input.length === 0) {
|
|
103
|
-
return [];
|
|
104
|
-
}
|
|
105
|
+
assertPitches(pitches, "key detection pitches", opts.budget);
|
|
105
106
|
const weights = opts.weights;
|
|
106
107
|
if (weights !== void 0 && weights.length !== pitches.length) {
|
|
107
|
-
throw new (0,
|
|
108
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)("weights must have one entry per pitch");
|
|
108
109
|
}
|
|
109
110
|
const counts = /* @__PURE__ */ new Map();
|
|
110
111
|
let total = 0;
|
|
111
112
|
for (let index = 0; index < pitches.length; index += 1) {
|
|
112
113
|
const weight = weights === void 0 ? 1 : _nullishCoalesce(weights[index], () => ( 0));
|
|
113
|
-
|
|
114
|
+
_chunkPI3UXRWKcjs.assertFiniteNumber.call(void 0, weight, `weights[${index}]`);
|
|
114
115
|
if (weight <= 0) {
|
|
115
116
|
continue;
|
|
116
117
|
}
|
|
117
|
-
const pc =
|
|
118
|
+
const pc = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, _nullishCoalesce(pitches[index], () => ( 0)));
|
|
118
119
|
counts.set(pc, (_nullishCoalesce(counts.get(pc), () => ( 0))) + weight);
|
|
119
120
|
total += weight;
|
|
120
121
|
}
|
|
121
122
|
if (total === 0) {
|
|
122
123
|
return [];
|
|
123
124
|
}
|
|
125
|
+
const input = [...counts.keys()];
|
|
124
126
|
const results = [];
|
|
125
127
|
for (let tonic = 0; tonic < 12; tonic += 1) {
|
|
126
128
|
for (const mode of ["major", "minor"]) {
|
|
@@ -163,11 +165,18 @@ function detectKey(pitches, opts = {}) {
|
|
|
163
165
|
return results;
|
|
164
166
|
}
|
|
165
167
|
var DEFAULT_VELOCITY = 100;
|
|
166
|
-
function detectKeyFromNotes(notes) {
|
|
168
|
+
function detectKeyFromNotes(notes, opts = {}) {
|
|
169
|
+
_chunkPI3UXRWKcjs.assertNoteEvents.call(void 0, notes, "key detection notes", {
|
|
170
|
+
allowNonPositiveDuration: true,
|
|
171
|
+
budget: opts.budget
|
|
172
|
+
});
|
|
167
173
|
const sounding = notes.filter((note) => note.durationBeat > 0);
|
|
168
174
|
return detectKey(
|
|
169
175
|
sounding.map((note) => note.pitch),
|
|
170
|
-
{
|
|
176
|
+
{
|
|
177
|
+
weights: sounding.map((note) => note.durationBeat * (_nullishCoalesce(note.velocity, () => ( DEFAULT_VELOCITY)))),
|
|
178
|
+
budget: opts.budget
|
|
179
|
+
}
|
|
171
180
|
);
|
|
172
181
|
}
|
|
173
182
|
function detectKeyBest(pitches, opts = {}) {
|
|
@@ -176,34 +185,38 @@ function detectKeyBest(pitches, opts = {}) {
|
|
|
176
185
|
|
|
177
186
|
// src/analyze/functional/internal.ts
|
|
178
187
|
function degreeRootPc(degreeNumber, key) {
|
|
179
|
-
const tones =
|
|
188
|
+
const tones = _chunkBSLTLGM3cjs.scaleTonesInDegreeOrder.call(void 0, key);
|
|
180
189
|
if (tones.length === 0) {
|
|
181
|
-
return
|
|
190
|
+
return _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
182
191
|
}
|
|
183
192
|
const index = ((degreeNumber - 1) % tones.length + tones.length) % tones.length;
|
|
184
|
-
return _nullishCoalesce(tones[index], () => (
|
|
193
|
+
return _nullishCoalesce(tones[index], () => ( _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, key.rootPc)));
|
|
185
194
|
}
|
|
186
195
|
function loweredDegrees(key) {
|
|
187
|
-
const tones =
|
|
196
|
+
const tones = _chunkBSLTLGM3cjs.scaleTonesInDegreeOrder.call(void 0, key);
|
|
188
197
|
const out = /* @__PURE__ */ new Set();
|
|
189
198
|
if (tones.length !== 7) {
|
|
190
199
|
return out;
|
|
191
200
|
}
|
|
192
|
-
const major =
|
|
201
|
+
const major = _chunkBSLTLGM3cjs.scaleTonesInDegreeOrder.call(void 0, { rootPc: _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunkBSLTLGM3cjs.MAJOR_MASK });
|
|
193
202
|
for (let index = 0; index < 7; index += 1) {
|
|
194
203
|
const tone = tones[index];
|
|
195
204
|
const majorTone = major[index];
|
|
196
|
-
if (tone !== void 0 && majorTone !== void 0 &&
|
|
205
|
+
if (tone !== void 0 && majorTone !== void 0 && _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, majorTone - tone) === 1) {
|
|
197
206
|
out.add(index + 1);
|
|
198
207
|
}
|
|
199
208
|
}
|
|
200
209
|
return out;
|
|
201
210
|
}
|
|
202
211
|
function romanReference(key) {
|
|
203
|
-
return
|
|
212
|
+
return _chunkBSLTLGM3cjs.scaleTonesInDegreeOrder.call(void 0, key).length === 7 ? key : _chunkBSLTLGM3cjs.majorKey.call(void 0, _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, key.rootPc));
|
|
204
213
|
}
|
|
205
214
|
function isNeapolitan(chord, key) {
|
|
206
|
-
return
|
|
215
|
+
return _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc) === 1 && chord.quality === "maj";
|
|
216
|
+
}
|
|
217
|
+
function isAppliedDominantSonority(chord) {
|
|
218
|
+
const has = (semitones) => chord.intervals.some((i) => _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, i) === semitones);
|
|
219
|
+
return chord.quality === "maj" || has(4) && has(10);
|
|
207
220
|
}
|
|
208
221
|
|
|
209
222
|
// src/analyze/functional/roman.ts
|
|
@@ -255,6 +268,9 @@ var ROMAN_STYLE = {
|
|
|
255
268
|
dim7: { lower: true, suffix: "o7" },
|
|
256
269
|
m7b5: { lower: true, suffix: "\xF87" },
|
|
257
270
|
minMaj7: { lower: true, suffix: "maj7" },
|
|
271
|
+
minMaj9: { lower: true, suffix: "maj9" },
|
|
272
|
+
minMaj11: { lower: true, suffix: "maj11" },
|
|
273
|
+
minMaj13: { lower: true, suffix: "maj13" },
|
|
258
274
|
aug7: { lower: false, suffix: "+7" },
|
|
259
275
|
augMaj7: { lower: false, suffix: "+maj7" },
|
|
260
276
|
majb5: { lower: false, suffix: "b5" },
|
|
@@ -315,26 +331,33 @@ function parseInversion(figures) {
|
|
|
315
331
|
function parseSimpleRoman(text, key) {
|
|
316
332
|
const match = /^([b#]?)([iIvV]+)(.*)$/.exec(text.trim());
|
|
317
333
|
if (!match) {
|
|
318
|
-
throw new (0,
|
|
334
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(`Invalid Roman numeral: ${text}`);
|
|
335
|
+
}
|
|
336
|
+
const glyphText = _nullishCoalesce(match[2], () => ( ""));
|
|
337
|
+
if (glyphText !== glyphText.toUpperCase() && glyphText !== glyphText.toLowerCase()) {
|
|
338
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(`Roman numeral must use one case: ${text}`);
|
|
319
339
|
}
|
|
320
340
|
const accidental = match[1] === "b" ? -1 : match[1] === "#" ? 1 : 0;
|
|
321
|
-
const glyph =
|
|
341
|
+
const glyph = glyphText.toUpperCase();
|
|
322
342
|
const degreeNumber = ROMAN_TO_DEGREE[glyph];
|
|
323
343
|
if (degreeNumber === void 0) {
|
|
324
|
-
throw new (0,
|
|
344
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(`Invalid Roman numeral: ${text}`);
|
|
325
345
|
}
|
|
326
|
-
const isUpper =
|
|
346
|
+
const isUpper = glyphText[0] === _optionalChain([glyphText, 'access', _ => _[0], 'optionalAccess', _2 => _2.toUpperCase, 'call', _3 => _3()]);
|
|
327
347
|
const suffix = _nullishCoalesce(match[3], () => ( ""));
|
|
328
348
|
const frame = romanReference(key);
|
|
329
349
|
const redundantFlat = accidental === -1 && loweredDegrees(frame).has(degreeNumber);
|
|
330
|
-
const
|
|
350
|
+
const diatonicRootPc = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0,
|
|
351
|
+
degreeRootPc(degreeNumber, frame) + (redundantFlat ? 0 : accidental)
|
|
352
|
+
);
|
|
353
|
+
const rootForQuality = (quality2) => accidental === 0 && degreeNumber === 7 && loweredDegrees(frame).has(7) && (quality2 === "dim" || quality2 === "dim7") ? _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, diatonicRootPc + 1) : diatonicRootPc;
|
|
331
354
|
const canonical = SUFFIX_QUALITY.get(`${isUpper ? "u" : "l"}:${suffix}`);
|
|
332
355
|
if (canonical !== void 0) {
|
|
333
|
-
return { rootPc, quality: canonical, inversion: 0 };
|
|
356
|
+
return { rootPc: rootForQuality(canonical), quality: canonical, inversion: 0 };
|
|
334
357
|
}
|
|
335
358
|
const parsedSuffix = /^(o|°|dim|ø|\+|aug)?(maj7|M7)?(65|64|43|42|7|6|2)?$/.exec(suffix);
|
|
336
359
|
if (!parsedSuffix) {
|
|
337
|
-
throw new (0,
|
|
360
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(`Unsupported suffix "${suffix}" in Roman numeral: ${text}`);
|
|
338
361
|
}
|
|
339
362
|
const qualityMarker = _nullishCoalesce(parsedSuffix[1], () => ( ""));
|
|
340
363
|
const isDim = qualityMarker === "o" || qualityMarker === "\xB0" || qualityMarker === "dim";
|
|
@@ -343,7 +366,7 @@ function parseSimpleRoman(text, key) {
|
|
|
343
366
|
const explicitMaj7 = parsedSuffix[2] !== void 0;
|
|
344
367
|
const figures = _nullishCoalesce(parsedSuffix[3], () => ( ""));
|
|
345
368
|
if (figures !== "" && !INVERSION_FIGURES.has(figures)) {
|
|
346
|
-
throw new (0,
|
|
369
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(
|
|
347
370
|
`Unsupported figured-bass or extension "${figures}" in Roman numeral: ${text}`
|
|
348
371
|
);
|
|
349
372
|
}
|
|
@@ -369,23 +392,23 @@ function parseSimpleRoman(text, key) {
|
|
|
369
392
|
} else {
|
|
370
393
|
quality = base;
|
|
371
394
|
}
|
|
372
|
-
return { rootPc, quality, inversion };
|
|
395
|
+
return { rootPc: rootForQuality(quality), quality, inversion };
|
|
373
396
|
}
|
|
374
397
|
function chordFromParsed(parsed) {
|
|
375
|
-
const chord =
|
|
398
|
+
const chord = _chunkBSLTLGM3cjs.makeChord.call(void 0, parsed.rootPc, parsed.quality);
|
|
376
399
|
if (parsed.inversion > 0 && parsed.inversion < chord.intervals.length) {
|
|
377
|
-
chord.bassPc =
|
|
400
|
+
chord.bassPc = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, parsed.rootPc + (_nullishCoalesce(chord.intervals[parsed.inversion], () => ( 0))));
|
|
378
401
|
}
|
|
379
402
|
return chord;
|
|
380
403
|
}
|
|
381
404
|
function romanToChord(text, key) {
|
|
382
|
-
const trimmed = text.trim();
|
|
405
|
+
const trimmed = text.trim().replace(/(\d)\/(?=\d)/g, "$1");
|
|
383
406
|
const slash = trimmed.indexOf("/");
|
|
384
407
|
if (slash >= 0) {
|
|
385
408
|
const applied = trimmed.slice(0, slash);
|
|
386
409
|
const target = trimmed.slice(slash + 1);
|
|
387
410
|
const targetRoot = parseSimpleRoman(target, key).rootPc;
|
|
388
|
-
const localKey =
|
|
411
|
+
const localKey = _chunkBSLTLGM3cjs.majorKey.call(void 0, targetRoot);
|
|
389
412
|
return chordFromParsed(parseSimpleRoman(applied, localKey));
|
|
390
413
|
}
|
|
391
414
|
return chordFromParsed(parseSimpleRoman(trimmed, key));
|
|
@@ -394,14 +417,14 @@ function romanStyle(quality) {
|
|
|
394
417
|
return ROMAN_STYLE[quality];
|
|
395
418
|
}
|
|
396
419
|
function romanSpelling(rootPc, key) {
|
|
397
|
-
const tones =
|
|
398
|
-
const diatonic = tones.indexOf(
|
|
420
|
+
const tones = _chunkBSLTLGM3cjs.scaleTonesInDegreeOrder.call(void 0, romanReference(key));
|
|
421
|
+
const diatonic = tones.indexOf(_chunkPI3UXRWKcjs.pitchClassOf.call(void 0, rootPc));
|
|
399
422
|
if (diatonic >= 0) {
|
|
400
423
|
return { degreeNumber: diatonic + 1, accidental: "" };
|
|
401
424
|
}
|
|
402
425
|
const lowered = loweredDegrees(romanReference(key));
|
|
403
426
|
for (let i = 0; i < tones.length; i += 1) {
|
|
404
|
-
if (lowered.has(i + 1) &&
|
|
427
|
+
if (lowered.has(i + 1) && _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) + 1) === _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
405
428
|
return { degreeNumber: i + 1, accidental: "#" };
|
|
406
429
|
}
|
|
407
430
|
}
|
|
@@ -410,16 +433,16 @@ function romanSpelling(rootPc, key) {
|
|
|
410
433
|
if (degreeNumber2 === 1 || degreeNumber2 === 5) {
|
|
411
434
|
continue;
|
|
412
435
|
}
|
|
413
|
-
if (
|
|
436
|
+
if (_chunkPI3UXRWKcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) - 1) === _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
414
437
|
return { degreeNumber: degreeNumber2, accidental: "b" };
|
|
415
438
|
}
|
|
416
439
|
}
|
|
417
440
|
for (let i = 0; i < tones.length; i += 1) {
|
|
418
|
-
if (
|
|
441
|
+
if (_chunkPI3UXRWKcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[i], () => ( 0))) + 1) === _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, rootPc)) {
|
|
419
442
|
return { degreeNumber: i + 1, accidental: "#" };
|
|
420
443
|
}
|
|
421
444
|
}
|
|
422
|
-
const [degreeNumber, accidental] = _nullishCoalesce(OFFSET_SPELLING[
|
|
445
|
+
const [degreeNumber, accidental] = _nullishCoalesce(OFFSET_SPELLING[_chunkPI3UXRWKcjs.pitchClassOf.call(void 0, rootPc - key.rootPc)], () => ( [1, ""]));
|
|
423
446
|
return { degreeNumber, accidental };
|
|
424
447
|
}
|
|
425
448
|
function baseMarker(quality) {
|
|
@@ -456,23 +479,19 @@ var SEVENTH_FIGURE_QUALITIES = /* @__PURE__ */ new Set([
|
|
|
456
479
|
function numeralFor(degreeNumber, lower) {
|
|
457
480
|
const glyph = ROMAN[degreeNumber - 1];
|
|
458
481
|
if (glyph === void 0) {
|
|
459
|
-
throw new (0,
|
|
482
|
+
throw new (0, _chunkPI3UXRWKcjs.InvalidInputError)(`no Roman numeral for scale degree ${degreeNumber}`);
|
|
460
483
|
}
|
|
461
484
|
return lower ? glyph.toLowerCase() : glyph;
|
|
462
485
|
}
|
|
463
486
|
function isDiatonicChord(chord, key) {
|
|
464
|
-
return
|
|
465
|
-
}
|
|
466
|
-
function isAppliedDominantSonority(chord) {
|
|
467
|
-
const has = (semitones) => chord.intervals.some((i) => _chunk7MGZ7D62cjs.pitchClassOf.call(void 0, i) === semitones);
|
|
468
|
-
return chord.quality === "maj" || has(4) && has(10);
|
|
487
|
+
return _chunkBSLTLGM3cjs.chordPitchClasses.call(void 0, chord).every((pc) => _chunkBSLTLGM3cjs.isScaleTone.call(void 0, pc, key));
|
|
469
488
|
}
|
|
470
489
|
var LEADING_TONE_QUALITIES = /* @__PURE__ */ new Set(["dim", "dim7", "m7b5"]);
|
|
471
490
|
function degreeTriad(tones, index) {
|
|
472
491
|
const root = _nullishCoalesce(tones[index], () => ( 0));
|
|
473
492
|
return {
|
|
474
|
-
third:
|
|
475
|
-
fifth:
|
|
493
|
+
third: _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[(index + 2) % tones.length], () => ( 0))) - root),
|
|
494
|
+
fifth: _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, (_nullishCoalesce(tones[(index + 4) % tones.length], () => ( 0))) - root)
|
|
476
495
|
};
|
|
477
496
|
}
|
|
478
497
|
function appliedTarget(chord, key) {
|
|
@@ -481,18 +500,15 @@ function appliedTarget(chord, key) {
|
|
|
481
500
|
if (!dominant && !leadingTone) {
|
|
482
501
|
return null;
|
|
483
502
|
}
|
|
484
|
-
const tones =
|
|
503
|
+
const tones = _chunkBSLTLGM3cjs.scaleTonesInDegreeOrder.call(void 0, romanReference(key));
|
|
485
504
|
for (let index = 1; index < tones.length; index += 1) {
|
|
486
505
|
const targetRoot = tones[index];
|
|
487
506
|
if (targetRoot === void 0) {
|
|
488
507
|
continue;
|
|
489
508
|
}
|
|
490
509
|
const triad = degreeTriad(tones, index);
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
}
|
|
494
|
-
const expectedRoot = _chunk7MGZ7D62cjs.pitchClassOf.call(void 0, targetRoot + (dominant ? 7 : -1));
|
|
495
|
-
if (expectedRoot === _chunk7MGZ7D62cjs.pitchClassOf.call(void 0, chord.rootPc)) {
|
|
510
|
+
const expectedRoot = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, targetRoot + (dominant ? 7 : -1));
|
|
511
|
+
if (expectedRoot === _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, chord.rootPc)) {
|
|
496
512
|
return { degreeNumber: index + 1, rootPc: targetRoot, lower: triad.third === 3 };
|
|
497
513
|
}
|
|
498
514
|
}
|
|
@@ -502,16 +518,17 @@ function chordToRoman(chord, key, opts = {}) {
|
|
|
502
518
|
if (opts.applied === true && !isDiatonicChord(chord, key)) {
|
|
503
519
|
const target = appliedTarget(chord, key);
|
|
504
520
|
if (target !== null) {
|
|
505
|
-
const local = chordToRoman(chord,
|
|
521
|
+
const local = chordToRoman(chord, _chunkBSLTLGM3cjs.majorKey.call(void 0, target.rootPc));
|
|
506
522
|
return `${local}/${numeralFor(target.degreeNumber, target.lower)}`;
|
|
507
523
|
}
|
|
508
524
|
}
|
|
509
|
-
const { degreeNumber, accidental } = romanSpelling(chord.rootPc, key);
|
|
525
|
+
const { degreeNumber, accidental: spelledAccidental } = romanSpelling(chord.rootPc, key);
|
|
510
526
|
const { lower, suffix } = romanStyle(chord.quality);
|
|
511
527
|
const cased = numeralFor(degreeNumber, lower);
|
|
528
|
+
const accidental = spelledAccidental === "#" && degreeNumber === 7 && loweredDegrees(romanReference(key)).has(7) && (chord.quality === "dim" || chord.quality === "dim7") ? "" : spelledAccidental;
|
|
512
529
|
let inversion = 0;
|
|
513
530
|
if (chord.bassPc !== void 0) {
|
|
514
|
-
const idx = chord.intervals.findIndex((iv) =>
|
|
531
|
+
const idx = chord.intervals.findIndex((iv) => _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, chord.rootPc + iv) === chord.bassPc);
|
|
515
532
|
if (idx > 0) {
|
|
516
533
|
inversion = idx;
|
|
517
534
|
}
|
|
@@ -526,14 +543,20 @@ function chordToRoman(chord, key, opts = {}) {
|
|
|
526
543
|
}
|
|
527
544
|
|
|
528
545
|
// src/analyze/functional/borrowed.ts
|
|
529
|
-
function
|
|
530
|
-
|
|
546
|
+
function isMinorScaleAlteration(chord, key) {
|
|
547
|
+
if (!isMinorKey(key)) return false;
|
|
548
|
+
const alteredKey = { rootPc: _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunkBSLTLGM3cjs.HARMONIC_MINOR_MASK };
|
|
549
|
+
if (isDiatonic(chord, alteredKey)) return true;
|
|
550
|
+
return _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc) === 11 && isDiatonic(chord, { rootPc: _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, key.rootPc), modeMask12: _chunkBSLTLGM3cjs.MELODIC_MINOR_MASK });
|
|
531
551
|
}
|
|
532
552
|
function isBorrowedChord(chord, key) {
|
|
533
553
|
if (isDiatonic(chord, key)) {
|
|
534
554
|
return false;
|
|
535
555
|
}
|
|
536
|
-
if (
|
|
556
|
+
if (isNeapolitan(chord, key)) {
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
if (isMinorScaleAlteration(chord, key)) {
|
|
537
560
|
return false;
|
|
538
561
|
}
|
|
539
562
|
return isDiatonic(chord, parallelKey(key));
|
|
@@ -542,9 +565,7 @@ function borrowedSource(chord, key) {
|
|
|
542
565
|
if (isDiatonic(chord, key)) {
|
|
543
566
|
return null;
|
|
544
567
|
}
|
|
545
|
-
if (isNeapolitan(chord, key))
|
|
546
|
-
return "neapolitan";
|
|
547
|
-
}
|
|
568
|
+
if (isNeapolitan(chord, key)) return "neapolitan";
|
|
548
569
|
if (isBorrowedChord(chord, key)) {
|
|
549
570
|
return isMinorKey(key) ? "parallelMajor" : "parallelMinor";
|
|
550
571
|
}
|
|
@@ -578,13 +599,27 @@ var FUNCTION_BY_OFFSET = [
|
|
|
578
599
|
"dominant"
|
|
579
600
|
// 11 vii
|
|
580
601
|
];
|
|
602
|
+
var MINOR_FUNCTION_BY_OFFSET = [
|
|
603
|
+
"tonic",
|
|
604
|
+
"subdominant",
|
|
605
|
+
"subdominant",
|
|
606
|
+
"tonic",
|
|
607
|
+
"dominant",
|
|
608
|
+
"subdominant",
|
|
609
|
+
"dominant",
|
|
610
|
+
"dominant",
|
|
611
|
+
"tonic",
|
|
612
|
+
"tonic",
|
|
613
|
+
"subdominant",
|
|
614
|
+
"dominant"
|
|
615
|
+
];
|
|
581
616
|
function isMinorKey(key) {
|
|
582
617
|
const hasMinorThird = key.modeMask12 >> 3 & 1;
|
|
583
618
|
const hasMajorThird2 = key.modeMask12 >> 4 & 1;
|
|
584
619
|
return Boolean(hasMinorThird) && !hasMajorThird2;
|
|
585
620
|
}
|
|
586
621
|
function functionOf(chord, key) {
|
|
587
|
-
const offset =
|
|
622
|
+
const offset = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, chord.rootPc - key.rootPc);
|
|
588
623
|
if (isNeapolitan(chord, key)) {
|
|
589
624
|
return "subdominant";
|
|
590
625
|
}
|
|
@@ -594,65 +629,75 @@ function functionOf(chord, key) {
|
|
|
594
629
|
if (!isMinorKey(key) && hasMajorThird(chord) && (offset === 8 || offset === 10)) {
|
|
595
630
|
return "subdominant";
|
|
596
631
|
}
|
|
597
|
-
|
|
632
|
+
const functions = isMinorKey(key) ? MINOR_FUNCTION_BY_OFFSET : FUNCTION_BY_OFFSET;
|
|
633
|
+
return _nullishCoalesce(functions[offset], () => ( "tonic"));
|
|
598
634
|
}
|
|
599
635
|
function isAppliedDominant(chord, key) {
|
|
600
636
|
if (isDiatonic(chord, key)) {
|
|
601
637
|
return false;
|
|
602
638
|
}
|
|
603
|
-
const root =
|
|
604
|
-
const resolvesTo = (step) =>
|
|
605
|
-
if (
|
|
606
|
-
return resolvesTo(5) || resolvesTo(11);
|
|
639
|
+
const root = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, chord.rootPc);
|
|
640
|
+
const resolvesTo = (step) => _chunkBSLTLGM3cjs.isScaleTone.call(void 0, _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, root + step), key);
|
|
641
|
+
if (isAppliedDominantSonority(chord)) {
|
|
642
|
+
return chord.quality === "maj" ? resolvesTo(5) : resolvesTo(5) || resolvesTo(11);
|
|
607
643
|
}
|
|
608
644
|
return isDiminishedQuality(chord.quality) && resolvesTo(1);
|
|
609
645
|
}
|
|
610
646
|
function isDiatonic(chord, key) {
|
|
611
|
-
return
|
|
647
|
+
return _chunkBSLTLGM3cjs.chordPitchClasses.call(void 0, chord).every((pc) => _chunkBSLTLGM3cjs.isScaleTone.call(void 0, pc, key));
|
|
612
648
|
}
|
|
613
649
|
function parallelKey(key) {
|
|
614
650
|
return {
|
|
615
|
-
rootPc:
|
|
616
|
-
modeMask12: isMinorKey(key) ?
|
|
651
|
+
rootPc: _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, key.rootPc),
|
|
652
|
+
modeMask12: isMinorKey(key) ? _chunkBSLTLGM3cjs.MAJOR_MASK : _chunkBSLTLGM3cjs.NATURAL_MINOR_MASK
|
|
617
653
|
};
|
|
618
654
|
}
|
|
619
655
|
function isDiminishedQuality(quality) {
|
|
620
656
|
return quality === "dim" || quality === "dim7" || quality === "m7b5";
|
|
621
657
|
}
|
|
622
658
|
function hasMajorThird(chord) {
|
|
623
|
-
return chord.intervals.some((interval) =>
|
|
659
|
+
return chord.intervals.some((interval) => _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, interval) === 4);
|
|
624
660
|
}
|
|
625
|
-
function analyzeChord(chord, key) {
|
|
661
|
+
function analyzeChord(chord, key, opts = {}) {
|
|
626
662
|
const source = borrowedSource(chord, key);
|
|
627
663
|
return {
|
|
628
664
|
function: functionOf(chord, key),
|
|
629
665
|
borrowed: source !== null,
|
|
630
666
|
source,
|
|
631
|
-
roman: chordToRoman(chord, key)
|
|
667
|
+
roman: chordToRoman(chord, key, opts)
|
|
632
668
|
};
|
|
633
669
|
}
|
|
634
670
|
function secondaryDominant(targetDegree, key) {
|
|
635
|
-
|
|
671
|
+
const degreeCount = _chunkBSLTLGM3cjs.scaleTonesInDegreeOrder.call(void 0, key).length;
|
|
672
|
+
_chunkPI3UXRWKcjs.assertInteger.call(void 0, targetDegree, "targetDegree", 0, degreeCount - 1);
|
|
636
673
|
const targetRoot = degreeRootPc(targetDegree + 1, key);
|
|
637
|
-
return
|
|
674
|
+
return _chunkBSLTLGM3cjs.makeChord.call(void 0, _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, targetRoot + 7), "dom7");
|
|
638
675
|
}
|
|
639
676
|
|
|
640
677
|
// src/analyze/functional/cadence.ts
|
|
678
|
+
function hasDominantThird(chord) {
|
|
679
|
+
return chord.intervals.some((interval) => _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, interval) === 4);
|
|
680
|
+
}
|
|
681
|
+
function isLeadingToneDiminished(chord) {
|
|
682
|
+
return chord.quality === "dim" || chord.quality === "dim7" || chord.quality === "m7b5";
|
|
683
|
+
}
|
|
641
684
|
function detectCadence(from, to, key) {
|
|
642
|
-
const tonic =
|
|
643
|
-
const fromOffset =
|
|
644
|
-
const toOffset =
|
|
685
|
+
const tonic = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, key.rootPc);
|
|
686
|
+
const fromOffset = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, from.rootPc - tonic);
|
|
687
|
+
const toOffset = _chunkPI3UXRWKcjs.pitchClassOf.call(void 0, to.rootPc - tonic);
|
|
645
688
|
const deceptiveTargets = isMinorKey(key) ? [8] : [8, 9];
|
|
646
|
-
|
|
689
|
+
const dominant = fromOffset === 7 && hasDominantThird(from);
|
|
690
|
+
const leadingTone = fromOffset === 11 && isLeadingToneDiminished(from);
|
|
691
|
+
if ((dominant || leadingTone) && toOffset === 0) {
|
|
647
692
|
return "authentic";
|
|
648
693
|
}
|
|
649
694
|
if (fromOffset === 5 && toOffset === 0) {
|
|
650
695
|
return "plagal";
|
|
651
696
|
}
|
|
652
|
-
if (
|
|
697
|
+
if (dominant && deceptiveTargets.includes(toOffset)) {
|
|
653
698
|
return "deceptive";
|
|
654
699
|
}
|
|
655
|
-
if (toOffset === 7 && fromOffset !== 7) {
|
|
700
|
+
if (toOffset === 7 && hasDominantThird(to) && fromOffset !== 7) {
|
|
656
701
|
return "half";
|
|
657
702
|
}
|
|
658
703
|
return null;
|
|
@@ -676,4 +721,4 @@ function detectCadence(from, to, key) {
|
|
|
676
721
|
|
|
677
722
|
|
|
678
723
|
exports.detectChord = detectChord; exports.detectChordBest = detectChordBest; exports.detectKey = detectKey; exports.detectKeyFromNotes = detectKeyFromNotes; exports.detectKeyBest = detectKeyBest; exports.romanToChord = romanToChord; exports.chordToRoman = chordToRoman; exports.isMinorKey = isMinorKey; exports.functionOf = functionOf; exports.isDiatonic = isDiatonic; exports.parallelKey = parallelKey; exports.analyzeChord = analyzeChord; exports.secondaryDominant = secondaryDominant; exports.isBorrowedChord = isBorrowedChord; exports.borrowedSource = borrowedSource; exports.detectCadence = detectCadence;
|
|
679
|
-
//# sourceMappingURL=chunk-
|
|
724
|
+
//# sourceMappingURL=chunk-KQN2ZYND.cjs.map
|