@libraz/libcantus 0.9.5 → 1.0.1
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 +61 -270
- package/README_ja.md +61 -214
- package/dist/analyze/index.cjs +54 -7
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +200 -353
- package/dist/analyze/index.d.ts +200 -353
- package/dist/analyze/index.js +56 -9
- package/dist/chunk-2LCPM3EG.js +3224 -0
- package/dist/chunk-2LCPM3EG.js.map +1 -0
- package/dist/chunk-6XH6QZYQ.cjs +7647 -0
- package/dist/chunk-6XH6QZYQ.cjs.map +1 -0
- package/dist/chunk-6XPTBE7Y.cjs +49 -0
- package/dist/chunk-6XPTBE7Y.cjs.map +1 -0
- package/dist/chunk-AFM2ULJH.cjs +5121 -0
- package/dist/chunk-AFM2ULJH.cjs.map +1 -0
- package/dist/chunk-B6XNKWZV.cjs +3224 -0
- package/dist/chunk-B6XNKWZV.cjs.map +1 -0
- package/dist/chunk-E3F4AHAH.cjs +690 -0
- package/dist/chunk-E3F4AHAH.cjs.map +1 -0
- package/dist/{chunk-2PTFGVD7.js → chunk-ELCTZUJJ.js} +250 -132
- package/dist/chunk-ELCTZUJJ.js.map +1 -0
- package/dist/chunk-FVSI36UV.js +690 -0
- package/dist/chunk-FVSI36UV.js.map +1 -0
- package/dist/chunk-GEDTJHAC.cjs +1 -0
- package/dist/chunk-GEDTJHAC.cjs.map +1 -0
- package/dist/chunk-H3VORETI.js +2243 -0
- package/dist/chunk-H3VORETI.js.map +1 -0
- package/dist/chunk-H42UHPYW.js +1577 -0
- package/dist/chunk-H42UHPYW.js.map +1 -0
- package/dist/chunk-HFPS7JFD.js +1 -0
- package/dist/chunk-INHVXP6Z.js +3053 -0
- package/dist/chunk-INHVXP6Z.js.map +1 -0
- package/dist/chunk-K4ZJUGF4.cjs +379 -0
- package/dist/chunk-K4ZJUGF4.cjs.map +1 -0
- package/dist/chunk-KNJEKLKV.js +49 -0
- package/dist/chunk-KNJEKLKV.js.map +1 -0
- package/dist/chunk-MXO72PLY.cjs +211 -0
- package/dist/chunk-MXO72PLY.cjs.map +1 -0
- package/dist/chunk-NLEU4QSE.cjs +360 -0
- package/dist/chunk-NLEU4QSE.cjs.map +1 -0
- package/dist/chunk-OE6WK2Y2.cjs +1577 -0
- package/dist/chunk-OE6WK2Y2.cjs.map +1 -0
- package/dist/chunk-PKFNUHDY.js +7647 -0
- package/dist/chunk-PKFNUHDY.js.map +1 -0
- package/dist/chunk-Q2WGKJNN.cjs +1064 -0
- package/dist/chunk-Q2WGKJNN.cjs.map +1 -0
- package/dist/chunk-QYQQ5J6E.js +1 -0
- package/dist/chunk-QYQQ5J6E.js.map +1 -0
- package/dist/chunk-RHIJ3S4I.cjs +1 -0
- package/dist/chunk-RHIJ3S4I.cjs.map +1 -0
- package/dist/chunk-TTCLJX6D.js +211 -0
- package/dist/chunk-TTCLJX6D.js.map +1 -0
- package/dist/chunk-UADYAYAT.cjs +3053 -0
- package/dist/chunk-UADYAYAT.cjs.map +1 -0
- package/dist/chunk-VOHZB45S.js +5121 -0
- package/dist/chunk-VOHZB45S.js.map +1 -0
- package/dist/chunk-VTI6FOLB.js +1064 -0
- package/dist/chunk-VTI6FOLB.js.map +1 -0
- package/dist/chunk-WWURE4XT.cjs +2243 -0
- package/dist/chunk-WWURE4XT.cjs.map +1 -0
- package/dist/chunk-YH3BIKHH.js +360 -0
- package/dist/chunk-YH3BIKHH.js.map +1 -0
- package/dist/core/index.cjs +93 -6
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +87 -346
- package/dist/core/index.d.ts +87 -346
- package/dist/core/index.js +94 -7
- package/dist/generate/index.cjs +89 -10
- package/dist/generate/index.cjs.map +1 -1
- package/dist/generate/index.d.cts +436 -1094
- package/dist/generate/index.d.ts +436 -1094
- package/dist/generate/index.js +94 -15
- package/dist/index-9wcMhG73.d.ts +1095 -0
- package/dist/{index-Cfx8xgH0.d.ts → index-B4o55NDr.d.cts} +13 -9
- package/dist/index-B9MNZboQ.d.cts +770 -0
- package/dist/index-B9MNZboQ.d.ts +770 -0
- package/dist/index-BGFW-8P2.d.cts +2307 -0
- package/dist/index-BO6xE9YU.d.cts +1804 -0
- package/dist/index-BkGmlyI3.d.cts +470 -0
- package/dist/index-CCNJRG-P.d.cts +1095 -0
- package/dist/index-CGpRv5sl.d.cts +643 -0
- package/dist/index-C_8o--VE.d.cts +1242 -0
- package/dist/index-CgHqxdps.d.ts +2307 -0
- package/dist/index-Chbst3Jx.d.ts +1343 -0
- package/dist/index-Cj49F892.d.ts +470 -0
- package/dist/{index-x2vcsduE.d.cts → index-CunYKLiu.d.ts} +13 -9
- package/dist/index-D57QRbVn.d.ts +1804 -0
- package/dist/index-DInQqT8Q.d.cts +66 -0
- package/dist/index-DInQqT8Q.d.ts +66 -0
- package/dist/index-Dzr13q3d.d.cts +1343 -0
- package/dist/index-G1uwGGWQ.d.ts +643 -0
- package/dist/index-szBv3496.d.ts +1242 -0
- package/dist/index.cjs +348 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -15
- package/dist/index.d.ts +17 -15
- package/dist/index.js +397 -64
- package/dist/masks-DYbE485J.d.cts +445 -0
- package/dist/masks-DYbE485J.d.ts +445 -0
- package/dist/model/index.cjs +39 -7
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +4659 -249
- package/dist/model/index.d.ts +4659 -249
- package/dist/model/index.js +40 -8
- package/dist/positional-Cptlj-xs.d.ts +287 -0
- package/dist/positional-DvH_sd8u.d.cts +287 -0
- package/dist/theory/index.cjs +101 -7
- package/dist/theory/index.cjs.map +1 -1
- package/dist/theory/index.d.cts +511 -171
- package/dist/theory/index.d.ts +511 -171
- package/dist/theory/index.js +118 -24
- package/package.json +6 -4
- package/dist/chunk-2A2QMA74.cjs +0 -261
- package/dist/chunk-2A2QMA74.cjs.map +0 -1
- package/dist/chunk-2PTFGVD7.js.map +0 -1
- package/dist/chunk-357ZDPVU.cjs +0 -162
- package/dist/chunk-357ZDPVU.cjs.map +0 -1
- package/dist/chunk-3KX76RLG.js +0 -1548
- package/dist/chunk-3KX76RLG.js.map +0 -1
- package/dist/chunk-4VZ5MZAM.cjs +0 -889
- package/dist/chunk-4VZ5MZAM.cjs.map +0 -1
- package/dist/chunk-7EONYVI5.js +0 -1204
- package/dist/chunk-7EONYVI5.js.map +0 -1
- package/dist/chunk-7JEP3MFY.js +0 -162
- package/dist/chunk-7JEP3MFY.js.map +0 -1
- package/dist/chunk-AID75RN3.js +0 -3176
- package/dist/chunk-AID75RN3.js.map +0 -1
- package/dist/chunk-BSLTLGM3.cjs +0 -497
- package/dist/chunk-BSLTLGM3.cjs.map +0 -1
- package/dist/chunk-CU6VG2YM.cjs +0 -109
- package/dist/chunk-CU6VG2YM.cjs.map +0 -1
- package/dist/chunk-DZMHIGI4.js +0 -337
- package/dist/chunk-DZMHIGI4.js.map +0 -1
- package/dist/chunk-EDOTEABK.js +0 -109
- package/dist/chunk-EDOTEABK.js.map +0 -1
- package/dist/chunk-HN2OEUN2.js +0 -33
- package/dist/chunk-HN2OEUN2.js.map +0 -1
- package/dist/chunk-KBTTEX7Q.js +0 -497
- package/dist/chunk-KBTTEX7Q.js.map +0 -1
- package/dist/chunk-KQN2ZYND.cjs +0 -724
- package/dist/chunk-KQN2ZYND.cjs.map +0 -1
- package/dist/chunk-MPTVJIVG.cjs +0 -3176
- package/dist/chunk-MPTVJIVG.cjs.map +0 -1
- package/dist/chunk-MTMZTMWM.cjs +0 -53
- package/dist/chunk-MTMZTMWM.cjs.map +0 -1
- package/dist/chunk-N6IHQUOX.js +0 -1
- package/dist/chunk-NNB67XA2.js +0 -724
- package/dist/chunk-NNB67XA2.js.map +0 -1
- package/dist/chunk-OL3IHHSJ.cjs +0 -1204
- package/dist/chunk-OL3IHHSJ.cjs.map +0 -1
- package/dist/chunk-PI3UXRWK.cjs +0 -528
- package/dist/chunk-PI3UXRWK.cjs.map +0 -1
- package/dist/chunk-R2VVFAIN.js +0 -528
- package/dist/chunk-R2VVFAIN.js.map +0 -1
- package/dist/chunk-T64C7ZD7.cjs +0 -1
- package/dist/chunk-T64C7ZD7.cjs.map +0 -1
- package/dist/chunk-WFDXOLUB.cjs +0 -337
- package/dist/chunk-WFDXOLUB.cjs.map +0 -1
- package/dist/chunk-WTAN4ACG.cjs +0 -1548
- package/dist/chunk-WTAN4ACG.cjs.map +0 -1
- package/dist/chunk-YFJXS3AU.cjs +0 -33
- package/dist/chunk-YFJXS3AU.cjs.map +0 -1
- package/dist/chunk-YUE6TJ4M.js +0 -889
- package/dist/chunk-YUE6TJ4M.js.map +0 -1
- package/dist/chunk-ZGLJM4A4.js +0 -53
- package/dist/chunk-ZGLJM4A4.js.map +0 -1
- package/dist/function-CxixTB02.d.cts +0 -299
- package/dist/function-DTCt675z.d.ts +0 -299
- package/dist/index-B2Ulxxpo.d.cts +0 -144
- package/dist/index-BkYJ0xMq.d.cts +0 -152
- package/dist/index-BuaB-ypt.d.ts +0 -144
- package/dist/index-CAN7v-kw.d.ts +0 -199
- package/dist/index-COw1Ky9g.d.ts +0 -242
- package/dist/index-DRtIhlJj.d.ts +0 -152
- package/dist/index-DXd9JikN.d.cts +0 -246
- package/dist/index-DXd9JikN.d.ts +0 -246
- package/dist/index-alrRninU.d.cts +0 -199
- package/dist/index-oTQbYYIs.d.cts +0 -242
- package/dist/index-tR9jTn26.d.cts +0 -275
- package/dist/index-tR9jTn26.d.ts +0 -275
- package/dist/styled-Bl0ZK28h.d.ts +0 -543
- package/dist/styled-Crv6SA4S.d.cts +0 -543
- package/dist/types-BN6_Q9Kl.d.cts +0 -39
- package/dist/types-BN6_Q9Kl.d.ts +0 -39
- /package/dist/{chunk-N6IHQUOX.js.map → chunk-HFPS7JFD.js.map} +0 -0
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { K as KeyScale, N as NoteEvent } from './types-BN6_Q9Kl.cjs';
|
|
2
|
-
import { a as ChordQuality, C as Chord } from './index-oTQbYYIs.cjs';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Recognition: infer a chord name from a set of pitches, or a key from a set of
|
|
6
|
-
* pitch classes. This is the inverse direction of the chord/scale builders,
|
|
7
|
-
* which only go name -> notes.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A candidate chord interpretation of a pitch set.
|
|
12
|
-
*
|
|
13
|
-
* @category Recognition
|
|
14
|
-
*/
|
|
15
|
-
type ChordMatch = {
|
|
16
|
-
rootPc: number;
|
|
17
|
-
quality: ChordQuality;
|
|
18
|
-
/** Chord tones absent from the input (an incomplete voicing). */
|
|
19
|
-
missingPcs: number[];
|
|
20
|
-
/** Input pitch classes not belonging to the chord. */
|
|
21
|
-
extraPcs: number[];
|
|
22
|
-
/** True when the input pitch-class set equals the chord exactly. */
|
|
23
|
-
exact: boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Inversion implied by a known bass: 0 for root position, 1..n for an
|
|
26
|
-
* inversion. Null when no inversion can be named — either the input is an
|
|
27
|
-
* unordered pitch-class set with no bass, or the bass is not a chord tone (a
|
|
28
|
-
* pedal or passing bass), in which case `bassPc` still reports it.
|
|
29
|
-
*/
|
|
30
|
-
inversion: number | null;
|
|
31
|
-
/** Bass pitch class when the lowest note is not the root. */
|
|
32
|
-
bassPc?: number;
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* Input interpretation for {@link detectChord} and {@link detectChordBest}.
|
|
36
|
-
*
|
|
37
|
-
* @category Recognition
|
|
38
|
-
*/
|
|
39
|
-
type DetectChordOptions = {
|
|
40
|
-
/**
|
|
41
|
-
* `midi` uses the numerically lowest pitch as bass; `pitchClass` treats the
|
|
42
|
-
* input as unordered. `auto` (default) selects pitch-class mode only when all
|
|
43
|
-
* values lie in 0..11.
|
|
44
|
-
*/
|
|
45
|
-
input?: 'auto' | 'midi' | 'pitchClass';
|
|
46
|
-
/** Explicit bass pitch class, including for an unordered pitch-class set. */
|
|
47
|
-
bassPc?: number;
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* A candidate key interpretation of a pitch-class set.
|
|
51
|
-
*
|
|
52
|
-
* @category Recognition
|
|
53
|
-
*/
|
|
54
|
-
type KeyMatch = {
|
|
55
|
-
/** The scale that scored best for this tonic and mode, `variant` included. */
|
|
56
|
-
key: KeyScale;
|
|
57
|
-
mode: 'major' | 'minor';
|
|
58
|
-
/** Which scale form `key` uses; minor keys pick the best-scoring of the three. */
|
|
59
|
-
variant: KeyVariant;
|
|
60
|
-
/**
|
|
61
|
-
* Fraction of the distinct input pitch classes that belong to `key`, in
|
|
62
|
-
* [0, 1]. Measured against the returned scale, so it always agrees with
|
|
63
|
-
* `isScaleTone(pc, match.key)`. This is a coverage figure, not the ranking:
|
|
64
|
-
* see `score`.
|
|
65
|
-
*/
|
|
66
|
-
fit: number;
|
|
67
|
-
/**
|
|
68
|
-
* The value the results are ranked by, in [0, 1.5]. Unlike `fit` it counts
|
|
69
|
-
* every occurrence rather than every distinct pitch class, so a repeated tone
|
|
70
|
-
* weighs more, and it adds half a count per sounding of the tonic itself to
|
|
71
|
-
* break ties between keys that contain the same notes.
|
|
72
|
-
*/
|
|
73
|
-
score: number;
|
|
74
|
-
};
|
|
75
|
-
/**
|
|
76
|
-
* Which form of a scale a {@link KeyMatch} settled on.
|
|
77
|
-
*
|
|
78
|
-
* @category Recognition
|
|
79
|
-
*/
|
|
80
|
-
type KeyVariant = 'major' | 'natural' | 'harmonic' | 'melodic';
|
|
81
|
-
/**
|
|
82
|
-
* Input weighting for {@link detectKey}.
|
|
83
|
-
*
|
|
84
|
-
* @category Recognition
|
|
85
|
-
*/
|
|
86
|
-
type DetectKeyOptions = {
|
|
87
|
-
/**
|
|
88
|
-
* How much each pitch counts toward the histogram, one entry per pitch.
|
|
89
|
-
* Defaults to one per pitch, which weighs a thirty-second-note ornament as
|
|
90
|
-
* heavily as the whole note under it. {@link detectKeyFromNotes} supplies
|
|
91
|
-
* duration times velocity, matching how chord inference weighs its own
|
|
92
|
-
* histogram.
|
|
93
|
-
*/
|
|
94
|
-
weights?: readonly number[];
|
|
95
|
-
/**
|
|
96
|
-
* Upper bound on the input pitches processed by this detection call.
|
|
97
|
-
*
|
|
98
|
-
* @defaultValue {@link DEFAULT_GENERATION_BUDGET}
|
|
99
|
-
*/
|
|
100
|
-
budget?: number;
|
|
101
|
-
};
|
|
102
|
-
/**
|
|
103
|
-
* Identify chords matching a set of pitches.
|
|
104
|
-
*
|
|
105
|
-
* Every input pitch class is tried as a root against every known chord quality.
|
|
106
|
-
* A match is reported when all of the chord's tones are present in the input, or
|
|
107
|
-
* when the only absent tone is the perfect fifth (a common omission in shell
|
|
108
|
-
* voicings); matches are ranked best-first by fewest extra notes, then fewest
|
|
109
|
-
* missing notes, then most specific (largest) chord. An exact match (no extras,
|
|
110
|
-
* no missing) is flagged and ranked first.
|
|
111
|
-
*
|
|
112
|
-
* @param pitches MIDI pitches or bare pitch classes (octave-agnostic).
|
|
113
|
-
* @returns Ranked chord interpretations (may be empty).
|
|
114
|
-
* @example
|
|
115
|
-
* ```ts
|
|
116
|
-
* import { detectChord } from '@libraz/libcantus';
|
|
117
|
-
* const matches = detectChord([60, 64, 67]); // C E G
|
|
118
|
-
* matches[0]; // { rootPc: 0, quality: 'maj', exact: true, ... }
|
|
119
|
-
* ```
|
|
120
|
-
* @category Recognition
|
|
121
|
-
*/
|
|
122
|
-
declare function detectChord(pitches: readonly number[], opts?: DetectChordOptions): ChordMatch[];
|
|
123
|
-
/**
|
|
124
|
-
* The single best chord interpretation of a pitch set, or null if none.
|
|
125
|
-
*
|
|
126
|
-
* @param pitches MIDI pitches or bare pitch classes.
|
|
127
|
-
* @returns The top-ranked chord, or null when nothing matches.
|
|
128
|
-
* @example
|
|
129
|
-
* ```ts
|
|
130
|
-
* import { detectChordBest } from '@libraz/libcantus';
|
|
131
|
-
* detectChordBest([60, 64, 67]); // C major triad: { rootPc: 0, quality: 'maj', ... }
|
|
132
|
-
* ```
|
|
133
|
-
* @category Recognition
|
|
134
|
-
*/
|
|
135
|
-
declare function detectChordBest(pitches: readonly number[], opts?: DetectChordOptions): Chord | null;
|
|
136
|
-
/**
|
|
137
|
-
* Rank major and minor keys by how well they contain a set of pitch classes.
|
|
138
|
-
*
|
|
139
|
-
* Ranking is by `score`, which counts repetitions and adds a tonic weight so
|
|
140
|
-
* that, among equally-fitting keys, the one whose root is actually sounded is
|
|
141
|
-
* preferred. Minor candidates are scored against the natural, harmonic, and
|
|
142
|
-
* melodic minor variants and keep the best of the three, so a minor cadence
|
|
143
|
-
* containing the leading tone still resolves to its own tonic; the winning
|
|
144
|
-
* variant is what `key` and `variant` report, so `fit` describes the scale the
|
|
145
|
-
* caller receives. Returns all 24 keys ranked best-first, or an empty array for
|
|
146
|
-
* an empty input (mirroring {@link detectChord}).
|
|
147
|
-
*
|
|
148
|
-
* @param pitches MIDI pitches or bare pitch classes.
|
|
149
|
-
* @returns Ranked key interpretations (empty for an empty input).
|
|
150
|
-
* @example
|
|
151
|
-
* ```ts
|
|
152
|
-
* import { detectKey } from '@libraz/libcantus';
|
|
153
|
-
* const keys = detectKey([60, 62, 64, 65, 67, 69, 71]); // C major scale
|
|
154
|
-
* keys[0].mode; // 'major', with keys[0].key.rootPc === 0
|
|
155
|
-
* ```
|
|
156
|
-
* @category Recognition
|
|
157
|
-
*/
|
|
158
|
-
declare function detectKey(pitches: readonly number[], opts?: DetectKeyOptions): KeyMatch[];
|
|
159
|
-
/**
|
|
160
|
-
* Rank keys by how well they contain a set of note events, weighting each note
|
|
161
|
-
* by how much of the music it actually occupies.
|
|
162
|
-
*
|
|
163
|
-
* {@link detectKey} counts every pitch once, which lets a run of fast ornamental
|
|
164
|
-
* notes outvote the sustained harmony that establishes the key. This weighs
|
|
165
|
-
* each note by duration times velocity, the same measure chord inference uses,
|
|
166
|
-
* so the two agree on what the music emphasises. Notes that never sound (zero
|
|
167
|
-
* or negative duration) are ignored.
|
|
168
|
-
*
|
|
169
|
-
* @param notes The note events to weigh.
|
|
170
|
-
* @param opts Budget for processing imported note events.
|
|
171
|
-
* @returns Ranked key interpretations (empty when nothing sounds).
|
|
172
|
-
* @example
|
|
173
|
-
* ```ts
|
|
174
|
-
* import { detectKeyFromNotes } from '@libraz/libcantus';
|
|
175
|
-
* detectKeyFromNotes([{ pitch: 60, startBeat: 0, durationBeat: 4 }])[0]?.key.rootPc; // 0
|
|
176
|
-
* ```
|
|
177
|
-
* @category Recognition
|
|
178
|
-
*/
|
|
179
|
-
declare function detectKeyFromNotes(notes: readonly NoteEvent[], opts?: Omit<DetectKeyOptions, 'weights'>): KeyMatch[];
|
|
180
|
-
/**
|
|
181
|
-
* The single best key interpretation of a pitch set.
|
|
182
|
-
*
|
|
183
|
-
* The counterpart of {@link detectChordBest}: the ranked list is the general
|
|
184
|
-
* answer, but a caller that just wants "what key is this" should not have to
|
|
185
|
-
* index into it and assert the result is there.
|
|
186
|
-
*
|
|
187
|
-
* @param pitches MIDI pitches or bare pitch classes.
|
|
188
|
-
* @param opts How to weigh the input; see {@link DetectKeyOptions}.
|
|
189
|
-
* @returns The top-ranked key, or null when nothing sounds.
|
|
190
|
-
* @example
|
|
191
|
-
* ```ts
|
|
192
|
-
* import { detectKeyBest } from '@libraz/libcantus';
|
|
193
|
-
* detectKeyBest([0, 2, 4, 5, 7, 9, 11])?.mode; // 'major'
|
|
194
|
-
* ```
|
|
195
|
-
* @category Recognition
|
|
196
|
-
*/
|
|
197
|
-
declare function detectKeyBest(pitches: readonly number[], opts?: DetectKeyOptions): KeyMatch | null;
|
|
198
|
-
|
|
199
|
-
export { type ChordMatch as C, type DetectChordOptions as D, type KeyMatch as K, type DetectKeyOptions as a, type KeyVariant as b, detectChordBest as c, detectChord as d, detectKey as e, detectKeyBest as f, detectKeyFromNotes as g };
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
import { K as KeyScale } from './types-BN6_Q9Kl.cjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Chord quality identifiers understood by the chord builder.
|
|
5
|
-
*
|
|
6
|
-
* @category Chords
|
|
7
|
-
*/
|
|
8
|
-
type ChordQuality = 'maj' | 'min' | 'dim' | 'aug' | 'maj7' | 'min7' | 'dom7' | 'dim7' | 'm7b5' | 'minMaj7' | 'minMaj9' | 'minMaj11' | 'minMaj13' | 'aug7' | 'augMaj7' | 'majb5' | '6' | 'min6' | '6/9' | 'sus2' | 'sus4' | 'add9' | 'add11' | 'maj9' | 'min9' | 'dom9' | '7b9' | '7#9' | '7#11' | '7b13' | '11' | '13' | '5' | '7sus4' | '7b5' | '7alt' | '13b9' | 'maj13' | 'maj7#11' | 'min11' | 'min13' | 'minAdd9' | 'min6/9';
|
|
9
|
-
/**
|
|
10
|
-
* The basic role a chord tone plays: the degrees a chord's own template names.
|
|
11
|
-
*
|
|
12
|
-
* The shared vocabulary behind {@link chordToneRole}, the harmony layer's
|
|
13
|
-
* `HarmonyRole`, and the voice analyser's labels, so the three cannot drift.
|
|
14
|
-
*
|
|
15
|
-
* @category Chords
|
|
16
|
-
*/
|
|
17
|
-
type ChordToneRole = 'root' | 'third' | 'fifth' | 'sixth' | 'seventh';
|
|
18
|
-
/**
|
|
19
|
-
* A bare spelled pitch used as an enharmonic hint: a diatonic letter
|
|
20
|
-
* (0..6 = C..B) plus a chromatic alteration (-2 double-flat .. +2 double-sharp).
|
|
21
|
-
* Mirrors the letter/alter half of the pitch module's `Note` without an octave.
|
|
22
|
-
*
|
|
23
|
-
* @category Chords
|
|
24
|
-
*/
|
|
25
|
-
type PitchSpelling = {
|
|
26
|
-
letter: number;
|
|
27
|
-
alter: number;
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* A chord expressed as a root pitch class plus semitone offsets.
|
|
31
|
-
*
|
|
32
|
-
* `rootSpelling`/`bassSpelling` are optional enharmonic hints recorded by
|
|
33
|
-
* parsers (e.g. `parseChordSymbol('Bb7')`) so formatters can reproduce the
|
|
34
|
-
* original spelling instead of defaulting to sharps. Consumers may ignore
|
|
35
|
-
* them; a hint is only trusted when its pitch class still matches the
|
|
36
|
-
* corresponding `rootPc`/`bassPc`.
|
|
37
|
-
*
|
|
38
|
-
* @category Chords
|
|
39
|
-
*/
|
|
40
|
-
type Chord = {
|
|
41
|
-
rootPc: number;
|
|
42
|
-
quality: ChordQuality;
|
|
43
|
-
intervals: number[];
|
|
44
|
-
bassPc?: number;
|
|
45
|
-
rootSpelling?: PitchSpelling;
|
|
46
|
-
bassSpelling?: PitchSpelling;
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
* A chord positioned in time: a root pitch class and quality placed at a beat,
|
|
50
|
-
* with optional harmonic-analysis hints. Serves as the neutral exchange record
|
|
51
|
-
* between progression generators and timeline analysers.
|
|
52
|
-
*
|
|
53
|
-
* @category Composition
|
|
54
|
-
*/
|
|
55
|
-
type ChordSpan = {
|
|
56
|
-
rootPc: number;
|
|
57
|
-
quality: ChordQuality;
|
|
58
|
-
startBeat: number;
|
|
59
|
-
bassPc?: number;
|
|
60
|
-
/** 0-based scale degree of the chord root, when known. */
|
|
61
|
-
degree?: number;
|
|
62
|
-
/** True when the chord is a secondary dominant tonicizing another degree. */
|
|
63
|
-
secondaryDominant?: boolean;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* A chord occupying a half-open beat span `[startBeat, endBeat)`.
|
|
67
|
-
*
|
|
68
|
-
* The exchange record between anything that lays chords out in time — a
|
|
69
|
-
* timeline analysis, a bass-line plan, an accompaniment generator — so those
|
|
70
|
-
* surfaces share one definition instead of agreeing by coincidence.
|
|
71
|
-
*
|
|
72
|
-
* @category Composition
|
|
73
|
-
*/
|
|
74
|
-
type ChordSegment = {
|
|
75
|
-
startBeat: number;
|
|
76
|
-
endBeat: number;
|
|
77
|
-
chord: Chord;
|
|
78
|
-
};
|
|
79
|
-
/**
|
|
80
|
-
* All chord qualities the builder understands, in declaration order.
|
|
81
|
-
*
|
|
82
|
-
* The order is stable but carries no meaning: it is neither alphabetical nor
|
|
83
|
-
* sorted by template size. {@link detectChord} uses it as its final tie-break,
|
|
84
|
-
* so it is part of the observable behaviour and does not get reshuffled
|
|
85
|
-
* casually — but do not read it as a ranking.
|
|
86
|
-
*
|
|
87
|
-
* @category Chords
|
|
88
|
-
*/
|
|
89
|
-
declare function chordQualities(): ChordQuality[];
|
|
90
|
-
/**
|
|
91
|
-
* Build a chord rooted on a diatonic scale degree.
|
|
92
|
-
*
|
|
93
|
-
* The root pitch class is the degree's diatonic pitch class in `key`; the
|
|
94
|
-
* quality's interval template is attached unchanged. Degrees beyond the scale
|
|
95
|
-
* length wrap around.
|
|
96
|
-
*
|
|
97
|
-
* @param degree 0-based scale degree of the chord root.
|
|
98
|
-
* @param ext Chord quality to apply.
|
|
99
|
-
* @param key Key context supplying the diatonic root.
|
|
100
|
-
* @returns The constructed chord.
|
|
101
|
-
*
|
|
102
|
-
* @category Chords
|
|
103
|
-
*/
|
|
104
|
-
declare function chordFromDegree(degree: number, ext: ChordQuality, key: KeyScale): Chord;
|
|
105
|
-
/**
|
|
106
|
-
* Build a chord from an explicit root pitch class and quality.
|
|
107
|
-
*
|
|
108
|
-
* @param rootPc Root pitch class (0..11).
|
|
109
|
-
* @param quality Chord quality supplying the interval template.
|
|
110
|
-
* @param bassPc Optional slash-chord bass pitch class.
|
|
111
|
-
* @returns The constructed chord.
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```ts
|
|
115
|
-
* import { makeChord } from '@libraz/libcantus';
|
|
116
|
-
* const cmaj7 = makeChord(0, 'maj7');
|
|
117
|
-
* // { rootPc: 0, quality: 'maj7', intervals: [0, 4, 7, 11] }
|
|
118
|
-
* ```
|
|
119
|
-
*
|
|
120
|
-
* @category Chords
|
|
121
|
-
*/
|
|
122
|
-
declare function makeChord(rootPc: number, quality: ChordQuality, bassPc?: number): Chord;
|
|
123
|
-
/**
|
|
124
|
-
* Transpose a chord by a number of semitones.
|
|
125
|
-
*
|
|
126
|
-
* The interval template is carried over untouched, so a chord whose intervals
|
|
127
|
-
* were customised keeps them, and a slash bass moves with the root. Enharmonic
|
|
128
|
-
* spelling hints are dropped rather than shifted: the letter a transposed root
|
|
129
|
-
* should take depends on the destination key, which a semitone count does not
|
|
130
|
-
* carry. Pass the result through {@link spellChord} to respell it.
|
|
131
|
-
*
|
|
132
|
-
* @param chord The chord to transpose.
|
|
133
|
-
* @param semitones The signed semitone offset.
|
|
134
|
-
* @returns The transposed chord.
|
|
135
|
-
* @throws If `semitones` is not finite.
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* ```ts
|
|
139
|
-
* import { formatChordSymbol, parseChordSymbol, transposeChord } from '@libraz/libcantus';
|
|
140
|
-
* formatChordSymbol(transposeChord(parseChordSymbol('C/G'), 2)); // 'D/A'
|
|
141
|
-
* ```
|
|
142
|
-
*
|
|
143
|
-
* @category Chords
|
|
144
|
-
*/
|
|
145
|
-
declare function transposeChord(chord: Chord, semitones: number): Chord;
|
|
146
|
-
/**
|
|
147
|
-
* Get the sorted, deduplicated pitch classes of a chord.
|
|
148
|
-
*
|
|
149
|
-
* A slash bass is one of them: `F/G` sounds a G, the voicers put it in the
|
|
150
|
-
* bass, and a set that omitted it would not re-detect as the chord it came
|
|
151
|
-
* from. Pass `includeBass: false` to enumerate the interval template alone.
|
|
152
|
-
*
|
|
153
|
-
* @param chord The chord to enumerate.
|
|
154
|
-
* @param opts Set `includeBass: false` to omit a slash bass.
|
|
155
|
-
* @returns The chord's pitch classes, sorted ascending in [0, 11].
|
|
156
|
-
*
|
|
157
|
-
* @example
|
|
158
|
-
* ```ts
|
|
159
|
-
* import { makeChord, chordPitchClasses } from '@libraz/libcantus';
|
|
160
|
-
* chordPitchClasses(makeChord(0, 'maj7')); // [0, 4, 7, 11]
|
|
161
|
-
* chordPitchClasses(makeChord(5, 'maj', 7)); // [0, 5, 7, 9] — F/G, G included
|
|
162
|
-
* ```
|
|
163
|
-
*
|
|
164
|
-
* @category Chords
|
|
165
|
-
*/
|
|
166
|
-
declare function chordPitchClasses(chord: Chord, opts?: {
|
|
167
|
-
includeBass?: boolean;
|
|
168
|
-
}): number[];
|
|
169
|
-
/**
|
|
170
|
-
* A pitch's interval class above the chord root, in [0, 11].
|
|
171
|
-
*
|
|
172
|
-
* The shared reading of "where does this pitch sit in the chord", used by the
|
|
173
|
-
* safety evaluator and the voice analyser alike so they cannot disagree.
|
|
174
|
-
*
|
|
175
|
-
* @param pitch MIDI pitch or bare pitch class.
|
|
176
|
-
* @param chord The chord providing the root reference.
|
|
177
|
-
* @returns The interval class above the root.
|
|
178
|
-
* @category Chords
|
|
179
|
-
*/
|
|
180
|
-
declare function intervalAboveRoot(pitch: number, chord: Chord): number;
|
|
181
|
-
/**
|
|
182
|
-
* Whether a pitch is one of a chord's tones, ignoring octave.
|
|
183
|
-
*
|
|
184
|
-
* @param pitch MIDI pitch or bare pitch class.
|
|
185
|
-
* @param chord The chord, or null for no sounding harmony.
|
|
186
|
-
* @returns True when the pitch class belongs to the chord.
|
|
187
|
-
* @category Chords
|
|
188
|
-
*/
|
|
189
|
-
declare function isChordMember(pitch: number, chord: Chord | null): boolean;
|
|
190
|
-
/**
|
|
191
|
-
* Determine a pitch's harmonic role within a chord.
|
|
192
|
-
*
|
|
193
|
-
* The role is derived from the pitch's interval above the chord root, reduced
|
|
194
|
-
* modulo 12. A major sixth (9) reads as a `sixth` for sixth chords but as a
|
|
195
|
-
* `seventh` for a diminished-seventh chord; ninths and other tensions have no
|
|
196
|
-
* basic role and return null.
|
|
197
|
-
*
|
|
198
|
-
* @param pitch MIDI pitch or bare pitch class.
|
|
199
|
-
* @param chord The chord providing the root reference.
|
|
200
|
-
* @returns The chord-tone role, or null if the pitch has no basic role.
|
|
201
|
-
*
|
|
202
|
-
* @category Chords
|
|
203
|
-
*/
|
|
204
|
-
declare function chordToneRole(pitch: number, chord: Chord): ChordToneRole | null;
|
|
205
|
-
/**
|
|
206
|
-
* Build the diatonic triad rooted on a scale degree by stacking scale thirds.
|
|
207
|
-
*
|
|
208
|
-
* Unlike {@link chordFromDegree}, the chord quality is derived from the scale
|
|
209
|
-
* rather than supplied, so degrees yield their scale-correct triads (e.g. a
|
|
210
|
-
* diminished triad on the leading tone of a major key).
|
|
211
|
-
*
|
|
212
|
-
* @param degree 0-based scale degree of the chord root.
|
|
213
|
-
* @param key Key/scale context.
|
|
214
|
-
* @returns The diatonic triad.
|
|
215
|
-
* @throws If the scale is not heptatonic. Stacking thirds means skipping every
|
|
216
|
-
* other degree, which only lands on a triad when there are seven of them, so
|
|
217
|
-
* the pentatonic, blues, whole-tone, octatonic and chromatic scales have no
|
|
218
|
-
* diatonic triad; use {@link chordFromDegree} with an explicit quality there.
|
|
219
|
-
*
|
|
220
|
-
* @example
|
|
221
|
-
* ```ts
|
|
222
|
-
* import { majorKey, diatonicTriad } from '@libraz/libcantus';
|
|
223
|
-
* const tonic = diatonicTriad(0, majorKey(0)); // C major triad (degree 0 of C major)
|
|
224
|
-
* ```
|
|
225
|
-
*
|
|
226
|
-
* @category Chords
|
|
227
|
-
*/
|
|
228
|
-
declare function diatonicTriad(degree: number, key: KeyScale): Chord;
|
|
229
|
-
/**
|
|
230
|
-
* Build the diatonic seventh chord rooted on a scale degree.
|
|
231
|
-
*
|
|
232
|
-
* @param degree 0-based scale degree of the chord root.
|
|
233
|
-
* @param key Key/scale context.
|
|
234
|
-
* @returns The diatonic seventh chord.
|
|
235
|
-
* @throws If the scale is not heptatonic, for the reason given on
|
|
236
|
-
* {@link diatonicTriad}.
|
|
237
|
-
*
|
|
238
|
-
* @category Chords
|
|
239
|
-
*/
|
|
240
|
-
declare function diatonicSeventh(degree: number, key: KeyScale): Chord;
|
|
241
|
-
|
|
242
|
-
export { type Chord as C, type PitchSpelling as P, type ChordQuality as a, type ChordSegment as b, type ChordSpan as c, type ChordToneRole as d, chordFromDegree as e, chordPitchClasses as f, chordQualities as g, chordToneRole as h, diatonicSeventh as i, diatonicTriad as j, intervalAboveRoot as k, isChordMember as l, makeChord as m, transposeChord as t };
|