@libraz/libcantus 0.9.3 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/analyze/index.cjs +39 -1947
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +197 -37
- package/dist/analyze/index.d.ts +197 -37
- package/dist/analyze/index.js +19 -8
- package/dist/chunk-36N73KZ3.cjs +246 -0
- package/dist/chunk-36N73KZ3.cjs.map +1 -0
- package/dist/chunk-4HLLZPXT.cjs +3077 -0
- package/dist/chunk-4HLLZPXT.cjs.map +1 -0
- package/dist/chunk-7MGZ7D62.cjs +498 -0
- package/dist/chunk-7MGZ7D62.cjs.map +1 -0
- package/dist/{chunk-4MHA432G.js → chunk-7NKDPF74.js} +403 -180
- package/dist/chunk-7NKDPF74.js.map +1 -0
- package/dist/chunk-CAN76NCU.cjs +679 -0
- package/dist/chunk-CAN76NCU.cjs.map +1 -0
- package/dist/{chunk-MIWO425M.js → chunk-D2FAJBYL.js} +101 -34
- package/dist/chunk-D2FAJBYL.js.map +1 -0
- package/dist/{chunk-SGU7SPLK.js → chunk-EHVEBWM5.js} +1056 -531
- package/dist/chunk-EHVEBWM5.js.map +1 -0
- package/dist/chunk-FCANXBAT.cjs +30 -0
- package/dist/chunk-FCANXBAT.cjs.map +1 -0
- package/dist/chunk-FNDWXRRI.cjs +479 -0
- package/dist/chunk-FNDWXRRI.cjs.map +1 -0
- package/dist/{chunk-IT2O4XFE.js → chunk-GQSGS2N4.js} +43 -24
- package/dist/chunk-GQSGS2N4.js.map +1 -0
- package/dist/{chunk-62QZKCJQ.js → chunk-HKGYCQ34.js} +10 -6
- package/dist/chunk-HKGYCQ34.js.map +1 -0
- package/dist/{chunk-AKLYPWIN.js → chunk-I24MV65U.js} +29 -6
- package/dist/chunk-I24MV65U.js.map +1 -0
- package/dist/{chunk-CHMXELDS.js → chunk-KMHOICIY.js} +311 -181
- package/dist/chunk-KMHOICIY.js.map +1 -0
- package/dist/chunk-LW53AHQU.cjs +1117 -0
- package/dist/chunk-LW53AHQU.cjs.map +1 -0
- package/dist/{chunk-2ZWMSJH6.js → chunk-NKIBQ6PT.js} +2 -2
- package/dist/chunk-NKIBQ6PT.js.map +1 -0
- package/dist/chunk-NP4NA2FB.cjs +106 -0
- package/dist/chunk-NP4NA2FB.cjs.map +1 -0
- package/dist/chunk-NVE34YGZ.cjs +1449 -0
- package/dist/chunk-NVE34YGZ.cjs.map +1 -0
- package/dist/{chunk-EH6EM37U.js → chunk-NYYWMV2C.js} +61 -49
- package/dist/chunk-NYYWMV2C.js.map +1 -0
- package/dist/{chunk-GOAW4VYL.js → chunk-Q2XUP227.js} +243 -117
- package/dist/chunk-Q2XUP227.js.map +1 -0
- package/dist/chunk-Q6OP4U43.cjs +327 -0
- package/dist/chunk-Q6OP4U43.cjs.map +1 -0
- package/dist/chunk-RC6GBMCD.cjs +845 -0
- package/dist/chunk-RC6GBMCD.cjs.map +1 -0
- package/dist/{chunk-C5XYKUVG.js → chunk-RK35RIN7.js} +370 -157
- package/dist/chunk-RK35RIN7.js.map +1 -0
- package/dist/chunk-RUMU3UA6.cjs +53 -0
- package/dist/chunk-RUMU3UA6.cjs.map +1 -0
- package/dist/chunk-T64C7ZD7.cjs +1 -0
- package/dist/chunk-T64C7ZD7.cjs.map +1 -0
- package/dist/chunk-XEBG3G53.js +498 -0
- package/dist/chunk-XEBG3G53.js.map +1 -0
- package/dist/{chunk-I5R7ZBJS.js → chunk-YLEMGEFH.js} +103 -59
- package/dist/chunk-YLEMGEFH.js.map +1 -0
- package/dist/chunk-ZEJR4TKL.cjs +173 -0
- package/dist/chunk-ZEJR4TKL.cjs.map +1 -0
- package/dist/core/index.cjs +130 -647
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +301 -39
- package/dist/core/index.d.ts +301 -39
- package/dist/core/index.js +54 -16
- package/dist/{function-DYt4iKsn.d.cts → function-BtiZb9i9.d.ts} +28 -7
- package/dist/{function-DVH4Eusr.d.ts → function-DNugAOrt.d.cts} +28 -7
- package/dist/generate/index.cjs +28 -4085
- package/dist/generate/index.cjs.map +1 -1
- package/dist/generate/index.d.cts +370 -62
- package/dist/generate/index.d.ts +370 -62
- package/dist/generate/index.js +23 -9
- package/dist/{index-CxqBQtH1.d.cts → index-6VR8-kit.d.ts} +19 -4
- package/dist/index-70p168VM.d.ts +192 -0
- package/dist/{index-CpOsP1y9.d.cts → index-Be74mcon.d.cts} +18 -17
- package/dist/index-BtXT6UQ0.d.cts +192 -0
- package/dist/{index-DxvARIP2.d.ts → index-C5UBbQ4G.d.ts} +18 -17
- package/dist/{index-Bt4tOUD9.d.ts → index-C83mZI1P.d.ts} +93 -8
- package/dist/{index-Bg5dYMmZ.d.ts → index-D6b6na69.d.cts} +14 -11
- package/dist/{index-Cl7mhOFM.d.cts → index-DXd9JikN.d.cts} +92 -10
- package/dist/{index-Cl7mhOFM.d.ts → index-DXd9JikN.d.ts} +92 -10
- package/dist/index-OG65ocOr.d.cts +272 -0
- package/dist/index-OG65ocOr.d.ts +272 -0
- package/dist/{index-Jc0Ryi79.d.ts → index-tJhkmQgE.d.cts} +19 -4
- package/dist/{index-Dikst44v.d.cts → index-tSQh-xwY.d.ts} +14 -11
- package/dist/{index-BNlGP86A.d.cts → index-y_ak9_Hi.d.cts} +93 -8
- package/dist/index.cjs +419 -7383
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -14
- package/dist/index.d.ts +14 -14
- package/dist/index.js +111 -27
- package/dist/model/index.cjs +8 -2562
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +433 -75
- package/dist/model/index.d.ts +433 -75
- package/dist/model/index.js +6 -7
- package/dist/styled-DIRkk9Uz.d.ts +506 -0
- package/dist/styled-DJbkJQfj.d.cts +506 -0
- package/dist/theory/index.cjs +172 -1822
- package/dist/theory/index.cjs.map +1 -1
- package/dist/theory/index.d.cts +151 -233
- package/dist/theory/index.d.ts +151 -233
- package/dist/theory/index.js +30 -7
- package/dist/{types-MGP29r3t.d.cts → types-BN6_Q9Kl.d.cts} +11 -2
- package/dist/{types-MGP29r3t.d.ts → types-BN6_Q9Kl.d.ts} +11 -2
- package/package.json +24 -6
- package/dist/chunk-2ZWMSJH6.js.map +0 -1
- package/dist/chunk-4MHA432G.js.map +0 -1
- package/dist/chunk-62QZKCJQ.js.map +0 -1
- package/dist/chunk-AKLYPWIN.js.map +0 -1
- package/dist/chunk-C5XYKUVG.js.map +0 -1
- package/dist/chunk-CHMXELDS.js.map +0 -1
- package/dist/chunk-DYWFNC4A.js +0 -152
- package/dist/chunk-DYWFNC4A.js.map +0 -1
- package/dist/chunk-EH6EM37U.js.map +0 -1
- package/dist/chunk-FBQK3ZQN.js +0 -131
- package/dist/chunk-FBQK3ZQN.js.map +0 -1
- package/dist/chunk-GOAW4VYL.js.map +0 -1
- package/dist/chunk-I5R7ZBJS.js.map +0 -1
- package/dist/chunk-IT2O4XFE.js.map +0 -1
- package/dist/chunk-MIWO425M.js.map +0 -1
- package/dist/chunk-SGU7SPLK.js.map +0 -1
- package/dist/index-CGMZNCx6.d.cts +0 -140
- package/dist/index-CGMZNCx6.d.ts +0 -140
- package/dist/index-CnZCo29u.d.cts +0 -108
- package/dist/index-JnF4v9bx.d.ts +0 -108
- package/dist/styled-DZ7GjShb.d.ts +0 -282
- package/dist/styled-ZTbdaVFM.d.cts +0 -282
- package/src/analyze/arrange/index.ts +0 -21
- package/src/analyze/arrange/internal.ts +0 -127
- package/src/analyze/arrange/tension.ts +0 -199
- package/src/analyze/arrange/tracks.ts +0 -312
- package/src/analyze/detect/index.ts +0 -272
- package/src/analyze/functional/borrowed.ts +0 -84
- package/src/analyze/functional/cadence.ts +0 -66
- package/src/analyze/functional/function.ts +0 -184
- package/src/analyze/functional/index.ts +0 -23
- package/src/analyze/functional/internal.ts +0 -29
- package/src/analyze/functional/roman.ts +0 -402
- package/src/analyze/index.ts +0 -49
- package/src/analyze/timeline/index.ts +0 -451
- package/src/analyze/voice/index.ts +0 -339
- package/src/core/event-index/index.ts +0 -104
- package/src/core/index.ts +0 -61
- package/src/core/interval/index.ts +0 -81
- package/src/core/meter/index.ts +0 -302
- package/src/core/pitch/index.ts +0 -311
- package/src/core/random/index.ts +0 -76
- package/src/core/tuning/index.ts +0 -186
- package/src/core/types.ts +0 -29
- package/src/core/validation/index.ts +0 -119
- package/src/generate/bass/index.ts +0 -373
- package/src/generate/countermelody/index.ts +0 -470
- package/src/generate/drums/beat.ts +0 -266
- package/src/generate/drums/euclid.ts +0 -65
- package/src/generate/drums/fills.ts +0 -356
- package/src/generate/drums/ghost.ts +0 -119
- package/src/generate/drums/hihat.ts +0 -285
- package/src/generate/drums/hit.ts +0 -31
- package/src/generate/drums/index.ts +0 -361
- package/src/generate/drums/internal.ts +0 -257
- package/src/generate/drums/kick.ts +0 -160
- package/src/generate/drums/percussion.ts +0 -121
- package/src/generate/drums/rng.ts +0 -7
- package/src/generate/drums/swing.ts +0 -71
- package/src/generate/groove/index.ts +0 -351
- package/src/generate/harmonize/index.ts +0 -451
- package/src/generate/index.ts +0 -58
- package/src/generate/motif/index.ts +0 -422
- package/src/generate/progression/index.ts +0 -362
- package/src/generate/reharmony/index.ts +0 -323
- package/src/generate/rhythm/index.ts +0 -175
- package/src/index.ts +0 -13
- package/src/model/chord.ts +0 -442
- package/src/model/index.ts +0 -15
- package/src/model/interval.ts +0 -82
- package/src/model/key.ts +0 -266
- package/src/model/note.ts +0 -176
- package/src/model/progression.ts +0 -161
- package/src/model/shared.ts +0 -12
- package/src/theory/chord/index.ts +0 -375
- package/src/theory/chordscale/index.ts +0 -374
- package/src/theory/counterpoint/index.ts +0 -230
- package/src/theory/harmony/index.ts +0 -77
- package/src/theory/index.ts +0 -112
- package/src/theory/safety/index.ts +0 -488
- package/src/theory/scale/degrees.ts +0 -123
- package/src/theory/scale/index.ts +0 -28
- package/src/theory/scale/key.ts +0 -56
- package/src/theory/scale/masks.ts +0 -153
- package/src/theory/spelling/index.ts +0 -249
- package/src/theory/symbol/index.ts +0 -268
- package/src/theory/voicing/index.ts +0 -5
- package/src/theory/voicing/internal.ts +0 -168
- package/src/theory/voicing/leading.ts +0 -112
- package/src/theory/voicing/satb.ts +0 -216
- package/src/theory/voicing/styled.ts +0 -199
- package/tsconfig.json +0 -23
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import { K as KeyScale } from './types-
|
|
1
|
+
import { K as KeyScale } from './types-BN6_Q9Kl.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Chord quality identifiers understood by the chord builder.
|
|
5
5
|
*
|
|
6
6
|
* @category Chords
|
|
7
7
|
*/
|
|
8
|
-
type ChordQuality = 'maj' | 'min' | 'dim' | 'aug' | 'maj7' | 'min7' | 'dom7' | 'dim7' | 'm7b5' | 'minMaj7' | 'aug7' | 'augMaj7' | 'majb5' | '6' | 'min6' | '6/9' | 'sus2' | 'sus4' | 'add9' | 'add11' | 'maj9' | 'min9' | 'dom9' | '7b9' | '7#9' | '7#11' | '7b13' | '11' | '13' | '5';
|
|
8
|
+
type ChordQuality = 'maj' | 'min' | 'dim' | 'aug' | 'maj7' | 'min7' | 'dom7' | 'dim7' | 'm7b5' | 'minMaj7' | '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';
|
|
9
18
|
/**
|
|
10
19
|
* A bare spelled pitch used as an enharmonic hint: a diatonic letter
|
|
11
20
|
* (0..6 = C..B) plus a chromatic alteration (-2 double-flat .. +2 double-sharp).
|
|
@@ -54,7 +63,26 @@ type ChordSpan = {
|
|
|
54
63
|
secondaryDominant?: boolean;
|
|
55
64
|
};
|
|
56
65
|
/**
|
|
57
|
-
*
|
|
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.
|
|
58
86
|
*
|
|
59
87
|
* @category Chords
|
|
60
88
|
*/
|
|
@@ -92,21 +120,73 @@ declare function chordFromDegree(degree: number, ext: ChordQuality, key: KeyScal
|
|
|
92
120
|
* @category Chords
|
|
93
121
|
*/
|
|
94
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;
|
|
95
146
|
/**
|
|
96
147
|
* Get the sorted, deduplicated pitch classes of a chord.
|
|
97
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
|
+
*
|
|
98
153
|
* @param chord The chord to enumerate.
|
|
154
|
+
* @param opts Set `includeBass: false` to omit a slash bass.
|
|
99
155
|
* @returns The chord's pitch classes, sorted ascending in [0, 11].
|
|
100
156
|
*
|
|
101
157
|
* @example
|
|
102
158
|
* ```ts
|
|
103
159
|
* import { makeChord, chordPitchClasses } from '@libraz/libcantus';
|
|
104
160
|
* chordPitchClasses(makeChord(0, 'maj7')); // [0, 4, 7, 11]
|
|
161
|
+
* chordPitchClasses(makeChord(5, 'maj', 7)); // [0, 5, 7, 9] — F/G, G included
|
|
105
162
|
* ```
|
|
106
163
|
*
|
|
107
164
|
* @category Chords
|
|
108
165
|
*/
|
|
109
|
-
declare function chordPitchClasses(chord: Chord
|
|
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;
|
|
110
190
|
/**
|
|
111
191
|
* Determine a pitch's harmonic role within a chord.
|
|
112
192
|
*
|
|
@@ -121,18 +201,21 @@ declare function chordPitchClasses(chord: Chord): number[];
|
|
|
121
201
|
*
|
|
122
202
|
* @category Chords
|
|
123
203
|
*/
|
|
124
|
-
declare function chordToneRole(pitch: number, chord: Chord):
|
|
204
|
+
declare function chordToneRole(pitch: number, chord: Chord): ChordToneRole | null;
|
|
125
205
|
/**
|
|
126
206
|
* Build the diatonic triad rooted on a scale degree by stacking scale thirds.
|
|
127
207
|
*
|
|
128
208
|
* Unlike {@link chordFromDegree}, the chord quality is derived from the scale
|
|
129
209
|
* rather than supplied, so degrees yield their scale-correct triads (e.g. a
|
|
130
|
-
* diminished triad on the leading tone of a major key).
|
|
131
|
-
* scales; other scales stack by scale step regardless.
|
|
210
|
+
* diminished triad on the leading tone of a major key).
|
|
132
211
|
*
|
|
133
212
|
* @param degree 0-based scale degree of the chord root.
|
|
134
213
|
* @param key Key/scale context.
|
|
135
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.
|
|
136
219
|
*
|
|
137
220
|
* @example
|
|
138
221
|
* ```ts
|
|
@@ -149,9 +232,11 @@ declare function diatonicTriad(degree: number, key: KeyScale): Chord;
|
|
|
149
232
|
* @param degree 0-based scale degree of the chord root.
|
|
150
233
|
* @param key Key/scale context.
|
|
151
234
|
* @returns The diatonic seventh chord.
|
|
235
|
+
* @throws If the scale is not heptatonic, for the reason given on
|
|
236
|
+
* {@link diatonicTriad}.
|
|
152
237
|
*
|
|
153
238
|
* @category Chords
|
|
154
239
|
*/
|
|
155
240
|
declare function diatonicSeventh(degree: number, key: KeyScale): Chord;
|
|
156
241
|
|
|
157
|
-
export { type Chord as C, type PitchSpelling as P, type ChordQuality as a, type
|
|
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 };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { C as Chord } from './index-
|
|
1
|
+
import { d as ChordToneRole, C as Chord } from './index-y_ak9_Hi.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Harmonic role a pitch plays within a chord.
|
|
5
5
|
*
|
|
6
6
|
* @category Functional Harmony
|
|
7
7
|
*/
|
|
8
|
-
type HarmonyRole =
|
|
8
|
+
type HarmonyRole = ChordToneRole | 'tension' | 'doubling';
|
|
9
9
|
/**
|
|
10
10
|
* How firmly a pitch is locked to the chord's identity.
|
|
11
11
|
*
|
|
@@ -29,15 +29,18 @@ type VoicedRole = {
|
|
|
29
29
|
/**
|
|
30
30
|
* Classify a pitch's harmonic role and lock level within a chord.
|
|
31
31
|
*
|
|
32
|
-
* The role comes from the pitch's interval class above the chord root
|
|
33
|
-
* third (3/4), fifth (6/7/8),
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
32
|
+
* The role comes from the pitch's interval class above the chord root, read
|
|
33
|
+
* against the chord's own template: root (0), third (3/4), fifth (6/7/8),
|
|
34
|
+
* sixth or seventh (9/10/11). Every pitch the template does not claim is
|
|
35
|
+
* `'tension'` — including one that is simply foreign to the chord, which this
|
|
36
|
+
* single-pitch query cannot tell from a colour tone. The root locks the chord
|
|
37
|
+
* identity, the third locks its quality, and everything else is free voicing.
|
|
38
|
+
* In a suspended chord (a chord whose intervals include a 4th (5) or 2nd (2)
|
|
39
|
+
* but no third), the suspended tone takes the third's place as the
|
|
40
|
+
* quality-defining tone and is locked to `quality`, since moving it changes the
|
|
41
|
+
* chord. Detecting an octave doubling requires the surrounding voicing, which
|
|
42
|
+
* this query does not carry, so `'doubling'` is part of the type — the shared
|
|
43
|
+
* vocabulary of harmonic roles — but is never returned here.
|
|
41
44
|
*
|
|
42
45
|
* @param pitch MIDI pitch or bare pitch class.
|
|
43
46
|
* @param chord The chord providing the root reference.
|
|
@@ -16,9 +16,17 @@ type TimeSignature = {
|
|
|
16
16
|
/**
|
|
17
17
|
* Optional additive grouping of the bar's main pulses, as the felt-beat
|
|
18
18
|
* lengths in pulses — e.g. `[2, 2, 3]` for a 2+2+3 reading of 7/8, or
|
|
19
|
-
* `[3, 2]` for 5/8. The entries must be positive integers summing to
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* `[3, 2]` for 5/8. The entries must be positive integers summing to the
|
|
20
|
+
* numerator.
|
|
21
|
+
*
|
|
22
|
+
* A compound numerator accepts both readings. 9/8 groups its three dotted
|
|
23
|
+
* pulses as `[1, 1, 1]`, or reads additively as `[2, 2, 2, 3]` quavers; a
|
|
24
|
+
* grouping that sums to the numerator selects the additive reading, so
|
|
25
|
+
* aksak and other additive metres are expressible. {@link pulsesPerBar}
|
|
26
|
+
* and {@link isCompound} follow whichever reading the grouping selects.
|
|
27
|
+
*
|
|
28
|
+
* When present, the head pulse of each group (other than the downbeat) is
|
|
29
|
+
* treated as a secondary strong pulse by
|
|
22
30
|
* {@link metricWeight}/{@link isStrongBeat}; when absent, all main pulses
|
|
23
31
|
* are weighted equally as flat, evenly divided pulses.
|
|
24
32
|
*/
|
|
@@ -30,8 +38,13 @@ type TimeSignature = {
|
|
|
30
38
|
* @category Rhythm & Meter
|
|
31
39
|
*/
|
|
32
40
|
type BarPosition = {
|
|
41
|
+
/** 0-based bar index. {@link formatBarPosition} renders it 1-based. */
|
|
33
42
|
bar: number;
|
|
34
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Quarter-note offset from the start of the bar — not the felt beat. In 6/8
|
|
45
|
+
* the second felt beat is at `beat: 1.5`; {@link barPositionToPulse} converts
|
|
46
|
+
* to felt-beat numbering.
|
|
47
|
+
*/
|
|
35
48
|
beat: number;
|
|
36
49
|
};
|
|
37
50
|
/**
|
|
@@ -49,16 +62,34 @@ type BarPosition = {
|
|
|
49
62
|
*/
|
|
50
63
|
declare function parseTimeSignature(text: string): TimeSignature;
|
|
51
64
|
/**
|
|
52
|
-
* Render a time signature as `"n/d"
|
|
65
|
+
* Render a time signature as `"n/d"`, or as `"a+b+c/d"` when it carries an
|
|
66
|
+
* additive grouping and `grouping` is requested.
|
|
67
|
+
*
|
|
68
|
+
* The plain form drops the grouping, so a round trip through it reads 7/8 as
|
|
69
|
+
* flat rather than as 2+2+3; ask for the additive form to keep it.
|
|
53
70
|
*
|
|
71
|
+
* @param ts The time signature.
|
|
72
|
+
* @param opts Set `grouping: true` to render an additive grouping.
|
|
73
|
+
* @returns The formatted signature.
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { formatTimeSignature } from '@libraz/libcantus';
|
|
77
|
+
* const aksak = { numerator: 7, denominator: 8, grouping: [2, 2, 3] };
|
|
78
|
+
* formatTimeSignature(aksak); // '7/8'
|
|
79
|
+
* formatTimeSignature(aksak, { grouping: true }); // '2+2+3/8'
|
|
80
|
+
* ```
|
|
54
81
|
* @category Rhythm & Meter
|
|
55
82
|
*/
|
|
56
|
-
declare function formatTimeSignature(ts: TimeSignature
|
|
83
|
+
declare function formatTimeSignature(ts: TimeSignature, opts?: {
|
|
84
|
+
grouping?: boolean;
|
|
85
|
+
}): string;
|
|
57
86
|
/**
|
|
58
87
|
* Whether a meter is compound: its main pulses each divide into three, as in
|
|
59
88
|
* 6/8, 9/8, 12/8, or 6/4. Compound meters are those whose numerator is a
|
|
60
89
|
* multiple of three greater than three, independent of the denominator. Meters
|
|
61
|
-
* like 3/8 and 3/4 (simple triples, numerator 3) are not compound
|
|
90
|
+
* like 3/8 and 3/4 (simple triples, numerator 3) are not compound, and neither
|
|
91
|
+
* is a signature whose {@link TimeSignature.grouping} selects the additive
|
|
92
|
+
* reading (9/8 as 2+2+2+3).
|
|
62
93
|
*
|
|
63
94
|
* @param ts The time signature.
|
|
64
95
|
* @returns True for compound meters.
|
|
@@ -103,6 +134,57 @@ declare function pulsesPerBar(ts: TimeSignature): number;
|
|
|
103
134
|
* @category Rhythm & Meter
|
|
104
135
|
*/
|
|
105
136
|
declare function beatToBarPosition(beatInQuarters: number, ts: TimeSignature): BarPosition;
|
|
137
|
+
/**
|
|
138
|
+
* Length of one felt beat (main pulse) in quarter-note beats.
|
|
139
|
+
*
|
|
140
|
+
* A quarter note in simple meters, a dotted quarter in compound ones, and one
|
|
141
|
+
* denominator unit in an additive metre. Position displays, click tracks, and
|
|
142
|
+
* score export are all written against this length.
|
|
143
|
+
*
|
|
144
|
+
* @param ts The time signature.
|
|
145
|
+
* @returns The pulse length in quarter-note beats.
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* import { parseTimeSignature, pulseBeats } from '@libraz/libcantus';
|
|
149
|
+
* pulseBeats(parseTimeSignature('6/8')); // 1.5
|
|
150
|
+
* ```
|
|
151
|
+
* @category Rhythm & Meter
|
|
152
|
+
*/
|
|
153
|
+
declare function pulseBeats(ts: TimeSignature): number;
|
|
154
|
+
/**
|
|
155
|
+
* The felt-beat number of a bar position, 1-based.
|
|
156
|
+
*
|
|
157
|
+
* {@link BarPosition.beat} is a quarter-note offset, so in 6/8 the second felt
|
|
158
|
+
* beat reads as 1.5. This is the number a musician says and a position display
|
|
159
|
+
* shows.
|
|
160
|
+
*
|
|
161
|
+
* @param pos The bar position.
|
|
162
|
+
* @param ts The time signature.
|
|
163
|
+
* @returns The 1-based felt-beat number, fractional between pulses.
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* import { barPositionToPulse, parseTimeSignature } from '@libraz/libcantus';
|
|
167
|
+
* barPositionToPulse({ bar: 0, beat: 1.5 }, parseTimeSignature('6/8')); // 2
|
|
168
|
+
* ```
|
|
169
|
+
* @category Rhythm & Meter
|
|
170
|
+
*/
|
|
171
|
+
declare function barPositionToPulse(pos: BarPosition, ts: TimeSignature): number;
|
|
172
|
+
/**
|
|
173
|
+
* Render an absolute position as the `bar.beat` a DAW or a score shows:
|
|
174
|
+
* 1-based bar, 1-based felt beat.
|
|
175
|
+
*
|
|
176
|
+
* @param beatInQuarters Absolute position in quarter-note beats.
|
|
177
|
+
* @param ts The time signature.
|
|
178
|
+
* @param decimals Digits of the fractional beat to keep.
|
|
179
|
+
* @returns The formatted position, e.g. `'3.2'` for bar 3, felt beat 2.
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* import { formatBarPosition, parseTimeSignature } from '@libraz/libcantus';
|
|
183
|
+
* formatBarPosition(7.5, parseTimeSignature('6/8')); // '3.2'
|
|
184
|
+
* ```
|
|
185
|
+
* @category Rhythm & Meter
|
|
186
|
+
*/
|
|
187
|
+
declare function formatBarPosition(beatInQuarters: number, ts: TimeSignature, decimals?: number): string;
|
|
106
188
|
/**
|
|
107
189
|
* Convert a bar index and in-bar offset back to an absolute quarter-note
|
|
108
190
|
* position.
|
|
@@ -128,8 +210,8 @@ declare function barPositionToBeat(pos: BarPosition, ts: TimeSignature): number;
|
|
|
128
210
|
* @param beatInQuarters Absolute or in-bar quarter-note position.
|
|
129
211
|
* @param ts The time signature.
|
|
130
212
|
* @returns The metric weight (0–3).
|
|
131
|
-
* @throws If
|
|
132
|
-
* summing to
|
|
213
|
+
* @throws If the time signature is malformed, including a grouping that is not
|
|
214
|
+
* a positive-integer list summing to the pulse count or the numerator.
|
|
133
215
|
* @example
|
|
134
216
|
* ```ts
|
|
135
217
|
* import { parseTimeSignature, metricWeight } from '@libraz/libcantus';
|
|
@@ -161,4 +243,4 @@ declare function isStrongBeat(beatInQuarters: number, ts: TimeSignature): boolea
|
|
|
161
243
|
*/
|
|
162
244
|
declare function tuplet(totalBeats: number, count: number): number[];
|
|
163
245
|
|
|
164
|
-
export { type BarPosition as B, type TimeSignature as T,
|
|
246
|
+
export { type BarPosition as B, type TimeSignature as T, barPositionToPulse as a, barPositionToBeat as b, beatToBarPosition as c, beatsPerBar as d, formatTimeSignature as e, formatBarPosition as f, isStrongBeat as g, pulseBeats as h, isCompound as i, pulsesPerBar as j, metricWeight as m, parseTimeSignature as p, tuplet as t };
|
|
@@ -16,9 +16,17 @@ type TimeSignature = {
|
|
|
16
16
|
/**
|
|
17
17
|
* Optional additive grouping of the bar's main pulses, as the felt-beat
|
|
18
18
|
* lengths in pulses — e.g. `[2, 2, 3]` for a 2+2+3 reading of 7/8, or
|
|
19
|
-
* `[3, 2]` for 5/8. The entries must be positive integers summing to
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* `[3, 2]` for 5/8. The entries must be positive integers summing to the
|
|
20
|
+
* numerator.
|
|
21
|
+
*
|
|
22
|
+
* A compound numerator accepts both readings. 9/8 groups its three dotted
|
|
23
|
+
* pulses as `[1, 1, 1]`, or reads additively as `[2, 2, 2, 3]` quavers; a
|
|
24
|
+
* grouping that sums to the numerator selects the additive reading, so
|
|
25
|
+
* aksak and other additive metres are expressible. {@link pulsesPerBar}
|
|
26
|
+
* and {@link isCompound} follow whichever reading the grouping selects.
|
|
27
|
+
*
|
|
28
|
+
* When present, the head pulse of each group (other than the downbeat) is
|
|
29
|
+
* treated as a secondary strong pulse by
|
|
22
30
|
* {@link metricWeight}/{@link isStrongBeat}; when absent, all main pulses
|
|
23
31
|
* are weighted equally as flat, evenly divided pulses.
|
|
24
32
|
*/
|
|
@@ -30,8 +38,13 @@ type TimeSignature = {
|
|
|
30
38
|
* @category Rhythm & Meter
|
|
31
39
|
*/
|
|
32
40
|
type BarPosition = {
|
|
41
|
+
/** 0-based bar index. {@link formatBarPosition} renders it 1-based. */
|
|
33
42
|
bar: number;
|
|
34
|
-
/**
|
|
43
|
+
/**
|
|
44
|
+
* Quarter-note offset from the start of the bar — not the felt beat. In 6/8
|
|
45
|
+
* the second felt beat is at `beat: 1.5`; {@link barPositionToPulse} converts
|
|
46
|
+
* to felt-beat numbering.
|
|
47
|
+
*/
|
|
35
48
|
beat: number;
|
|
36
49
|
};
|
|
37
50
|
/**
|
|
@@ -49,16 +62,34 @@ type BarPosition = {
|
|
|
49
62
|
*/
|
|
50
63
|
declare function parseTimeSignature(text: string): TimeSignature;
|
|
51
64
|
/**
|
|
52
|
-
* Render a time signature as `"n/d"
|
|
65
|
+
* Render a time signature as `"n/d"`, or as `"a+b+c/d"` when it carries an
|
|
66
|
+
* additive grouping and `grouping` is requested.
|
|
67
|
+
*
|
|
68
|
+
* The plain form drops the grouping, so a round trip through it reads 7/8 as
|
|
69
|
+
* flat rather than as 2+2+3; ask for the additive form to keep it.
|
|
53
70
|
*
|
|
71
|
+
* @param ts The time signature.
|
|
72
|
+
* @param opts Set `grouping: true` to render an additive grouping.
|
|
73
|
+
* @returns The formatted signature.
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { formatTimeSignature } from '@libraz/libcantus';
|
|
77
|
+
* const aksak = { numerator: 7, denominator: 8, grouping: [2, 2, 3] };
|
|
78
|
+
* formatTimeSignature(aksak); // '7/8'
|
|
79
|
+
* formatTimeSignature(aksak, { grouping: true }); // '2+2+3/8'
|
|
80
|
+
* ```
|
|
54
81
|
* @category Rhythm & Meter
|
|
55
82
|
*/
|
|
56
|
-
declare function formatTimeSignature(ts: TimeSignature
|
|
83
|
+
declare function formatTimeSignature(ts: TimeSignature, opts?: {
|
|
84
|
+
grouping?: boolean;
|
|
85
|
+
}): string;
|
|
57
86
|
/**
|
|
58
87
|
* Whether a meter is compound: its main pulses each divide into three, as in
|
|
59
88
|
* 6/8, 9/8, 12/8, or 6/4. Compound meters are those whose numerator is a
|
|
60
89
|
* multiple of three greater than three, independent of the denominator. Meters
|
|
61
|
-
* like 3/8 and 3/4 (simple triples, numerator 3) are not compound
|
|
90
|
+
* like 3/8 and 3/4 (simple triples, numerator 3) are not compound, and neither
|
|
91
|
+
* is a signature whose {@link TimeSignature.grouping} selects the additive
|
|
92
|
+
* reading (9/8 as 2+2+2+3).
|
|
62
93
|
*
|
|
63
94
|
* @param ts The time signature.
|
|
64
95
|
* @returns True for compound meters.
|
|
@@ -103,6 +134,57 @@ declare function pulsesPerBar(ts: TimeSignature): number;
|
|
|
103
134
|
* @category Rhythm & Meter
|
|
104
135
|
*/
|
|
105
136
|
declare function beatToBarPosition(beatInQuarters: number, ts: TimeSignature): BarPosition;
|
|
137
|
+
/**
|
|
138
|
+
* Length of one felt beat (main pulse) in quarter-note beats.
|
|
139
|
+
*
|
|
140
|
+
* A quarter note in simple meters, a dotted quarter in compound ones, and one
|
|
141
|
+
* denominator unit in an additive metre. Position displays, click tracks, and
|
|
142
|
+
* score export are all written against this length.
|
|
143
|
+
*
|
|
144
|
+
* @param ts The time signature.
|
|
145
|
+
* @returns The pulse length in quarter-note beats.
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* import { parseTimeSignature, pulseBeats } from '@libraz/libcantus';
|
|
149
|
+
* pulseBeats(parseTimeSignature('6/8')); // 1.5
|
|
150
|
+
* ```
|
|
151
|
+
* @category Rhythm & Meter
|
|
152
|
+
*/
|
|
153
|
+
declare function pulseBeats(ts: TimeSignature): number;
|
|
154
|
+
/**
|
|
155
|
+
* The felt-beat number of a bar position, 1-based.
|
|
156
|
+
*
|
|
157
|
+
* {@link BarPosition.beat} is a quarter-note offset, so in 6/8 the second felt
|
|
158
|
+
* beat reads as 1.5. This is the number a musician says and a position display
|
|
159
|
+
* shows.
|
|
160
|
+
*
|
|
161
|
+
* @param pos The bar position.
|
|
162
|
+
* @param ts The time signature.
|
|
163
|
+
* @returns The 1-based felt-beat number, fractional between pulses.
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* import { barPositionToPulse, parseTimeSignature } from '@libraz/libcantus';
|
|
167
|
+
* barPositionToPulse({ bar: 0, beat: 1.5 }, parseTimeSignature('6/8')); // 2
|
|
168
|
+
* ```
|
|
169
|
+
* @category Rhythm & Meter
|
|
170
|
+
*/
|
|
171
|
+
declare function barPositionToPulse(pos: BarPosition, ts: TimeSignature): number;
|
|
172
|
+
/**
|
|
173
|
+
* Render an absolute position as the `bar.beat` a DAW or a score shows:
|
|
174
|
+
* 1-based bar, 1-based felt beat.
|
|
175
|
+
*
|
|
176
|
+
* @param beatInQuarters Absolute position in quarter-note beats.
|
|
177
|
+
* @param ts The time signature.
|
|
178
|
+
* @param decimals Digits of the fractional beat to keep.
|
|
179
|
+
* @returns The formatted position, e.g. `'3.2'` for bar 3, felt beat 2.
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* import { formatBarPosition, parseTimeSignature } from '@libraz/libcantus';
|
|
183
|
+
* formatBarPosition(7.5, parseTimeSignature('6/8')); // '3.2'
|
|
184
|
+
* ```
|
|
185
|
+
* @category Rhythm & Meter
|
|
186
|
+
*/
|
|
187
|
+
declare function formatBarPosition(beatInQuarters: number, ts: TimeSignature, decimals?: number): string;
|
|
106
188
|
/**
|
|
107
189
|
* Convert a bar index and in-bar offset back to an absolute quarter-note
|
|
108
190
|
* position.
|
|
@@ -128,8 +210,8 @@ declare function barPositionToBeat(pos: BarPosition, ts: TimeSignature): number;
|
|
|
128
210
|
* @param beatInQuarters Absolute or in-bar quarter-note position.
|
|
129
211
|
* @param ts The time signature.
|
|
130
212
|
* @returns The metric weight (0–3).
|
|
131
|
-
* @throws If
|
|
132
|
-
* summing to
|
|
213
|
+
* @throws If the time signature is malformed, including a grouping that is not
|
|
214
|
+
* a positive-integer list summing to the pulse count or the numerator.
|
|
133
215
|
* @example
|
|
134
216
|
* ```ts
|
|
135
217
|
* import { parseTimeSignature, metricWeight } from '@libraz/libcantus';
|
|
@@ -161,4 +243,4 @@ declare function isStrongBeat(beatInQuarters: number, ts: TimeSignature): boolea
|
|
|
161
243
|
*/
|
|
162
244
|
declare function tuplet(totalBeats: number, count: number): number[];
|
|
163
245
|
|
|
164
|
-
export { type BarPosition as B, type TimeSignature as T,
|
|
246
|
+
export { type BarPosition as B, type TimeSignature as T, barPositionToPulse as a, barPositionToBeat as b, beatToBarPosition as c, beatsPerBar as d, formatTimeSignature as e, formatBarPosition as f, isStrongBeat as g, pulseBeats as h, isCompound as i, pulsesPerBar as j, metricWeight as m, parseTimeSignature as p, tuplet as t };
|