@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,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { K as KeyScale, N as NoteEvent } from '../types-
|
|
3
|
-
import { C as Chord, a as ChordQuality,
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { B as BorrowedSource, H as HarmonicFunction } from '../function-DNugAOrt.cjs';
|
|
2
|
+
import { K as KeyScale, N as NoteEvent } from '../types-BN6_Q9Kl.cjs';
|
|
3
|
+
import { b as ChordSegment, C as Chord, a as ChordQuality, c as ChordSpan } from '../index-y_ak9_Hi.cjs';
|
|
4
|
+
export { d as ChordToneRole, P as PitchSpelling } from '../index-y_ak9_Hi.cjs';
|
|
5
|
+
import { a as ChordTimeline } from '../index-Be74mcon.cjs';
|
|
6
|
+
import { T as TimeSignature } from '../index-DXd9JikN.cjs';
|
|
7
|
+
import { H as HarmonyRole } from '../index-D6b6na69.cjs';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Deterministic bass-line generation over a chord placement.
|
|
@@ -22,19 +23,24 @@ import { B as BorrowedSource, H as HarmonicFunction } from '../function-DYt4iKsn
|
|
|
22
23
|
/**
|
|
23
24
|
* A chord sounding over a half-open beat span `[startBeat, endBeat)`.
|
|
24
25
|
*
|
|
26
|
+
* The same record {@link ChordSegment} names, so a timeline segment can be fed
|
|
27
|
+
* straight to the bass generator.
|
|
28
|
+
*
|
|
25
29
|
* @category Composition
|
|
26
30
|
*/
|
|
27
|
-
type BassSegment =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
type BassSegment = ChordSegment;
|
|
32
|
+
/**
|
|
33
|
+
* Every bass-line idiom, in declaration order.
|
|
34
|
+
*
|
|
35
|
+
* @category Composition
|
|
36
|
+
*/
|
|
37
|
+
declare const BASS_STYLES: readonly ["root", "rootFifth", "pop", "walking", "arpeggio"];
|
|
32
38
|
/**
|
|
33
39
|
* The bass-line idiom to generate.
|
|
34
40
|
*
|
|
35
41
|
* @category Composition
|
|
36
42
|
*/
|
|
37
|
-
type BassStyle =
|
|
43
|
+
type BassStyle = (typeof BASS_STYLES)[number];
|
|
38
44
|
/**
|
|
39
45
|
* Options controlling {@link generateBassLine}.
|
|
40
46
|
*
|
|
@@ -42,7 +48,7 @@ type BassStyle = 'root' | 'rootFifth' | 'pop' | 'walking' | 'arpeggio';
|
|
|
42
48
|
*/
|
|
43
49
|
type BassLineOptions = {
|
|
44
50
|
/** Chord placement to follow; need not be pre-sorted. */
|
|
45
|
-
segments: BassSegment[];
|
|
51
|
+
segments: readonly BassSegment[];
|
|
46
52
|
/** Key/scale context, used for diatonic approach tones in `walking`. */
|
|
47
53
|
key: KeyScale;
|
|
48
54
|
/**
|
|
@@ -59,6 +65,8 @@ type BassLineOptions = {
|
|
|
59
65
|
style?: BassStyle;
|
|
60
66
|
/**
|
|
61
67
|
* Target register as a base MIDI octave; roots land around `octave*12+12`.
|
|
68
|
+
* An octave pickup in the `pop` style may drop a note into the octave below
|
|
69
|
+
* that band, which is where such a pickup belongs.
|
|
62
70
|
*
|
|
63
71
|
* @defaultValue 2
|
|
64
72
|
*/
|
|
@@ -102,13 +110,28 @@ declare function generateBassLine(opts: BassLineOptions): NoteEvent[];
|
|
|
102
110
|
*/
|
|
103
111
|
type CounterMelodyOptions = {
|
|
104
112
|
/** The lead line to write against, in ascending onset order. */
|
|
105
|
-
melody: NoteEvent[];
|
|
106
|
-
/**
|
|
107
|
-
|
|
113
|
+
melody: readonly NoteEvent[];
|
|
114
|
+
/**
|
|
115
|
+
* The harmony to write against. A timeline carries its own segment
|
|
116
|
+
* boundaries, so a chord change anywhere — including off the generator's
|
|
117
|
+
* half-beat probe grid — is seen; prefer it over `chordAt`.
|
|
118
|
+
*
|
|
119
|
+
* Exactly one of `timeline` and `chordAt` is required; `timeline` wins when
|
|
120
|
+
* both are given.
|
|
121
|
+
*/
|
|
122
|
+
timeline?: ChordTimeline;
|
|
123
|
+
/**
|
|
124
|
+
* Chord sounding at an absolute beat position, or null when none applies.
|
|
125
|
+
*
|
|
126
|
+
* A callback is opaque: the generator cannot see where it changes, so it
|
|
127
|
+
* probes a half-beat grid and otherwise relies on `chordChangeBeats`. A held
|
|
128
|
+
* counter note that spans an unseen change is not checked against the new
|
|
129
|
+
* chord.
|
|
130
|
+
*/
|
|
131
|
+
chordAt?: (beat: number) => Chord | null;
|
|
108
132
|
/**
|
|
109
|
-
* Exact chord-change beats
|
|
110
|
-
*
|
|
111
|
-
* points are not introspectable and should be listed here.
|
|
133
|
+
* Exact chord-change beats the `chordAt` callback does not expose. Ignored
|
|
134
|
+
* when `timeline` is given, since a timeline lists its own boundaries.
|
|
112
135
|
*/
|
|
113
136
|
chordChangeBeats?: number[];
|
|
114
137
|
/** Key/scale context for scale-tone decisions. */
|
|
@@ -143,7 +166,11 @@ type CounterMelodyOptions = {
|
|
|
143
166
|
/** Highest MIDI pitch the counter line may use (default derived from `register`). */
|
|
144
167
|
pitchHigh?: number;
|
|
145
168
|
/**
|
|
146
|
-
* PRNG seed
|
|
169
|
+
* PRNG seed. It places the `'complement'` onsets and breaks ties between
|
|
170
|
+
* equally good candidate pitches; the same seed always yields the same line.
|
|
171
|
+
* Where the constraints leave only one good answer — which is common with
|
|
172
|
+
* `rhythm: 'follow'`, whose onsets are fixed by the melody — changing the seed
|
|
173
|
+
* changes nothing.
|
|
147
174
|
*
|
|
148
175
|
* @defaultValue 0
|
|
149
176
|
*/
|
|
@@ -159,8 +186,10 @@ type CounterMelodyOptions = {
|
|
|
159
186
|
* consonant tensions against the sounding melody note), rejecting candidates
|
|
160
187
|
* that would form a parallel perfect interval with the melody or sit on the
|
|
161
188
|
* wrong side of it, then scored to favour contrary or oblique motion, imperfect
|
|
162
|
-
* consonance, and stepwise movement. Ties
|
|
163
|
-
*
|
|
189
|
+
* consonance, and stepwise movement. Ties are broken by a seeded perturbation far
|
|
190
|
+
* below any real score difference (see `TIE_BREAK_JITTER`), so the same
|
|
191
|
+
* seed always yields the same line while a different seed can only reshuffle
|
|
192
|
+
* candidates that were already equally good. Notes extend to the next counter
|
|
164
193
|
* onset (the last to the melody's end) at a velocity slightly under the melody.
|
|
165
194
|
*
|
|
166
195
|
* @param opts The lead line, chord context callback, key, and generation knobs.
|
|
@@ -179,22 +208,92 @@ type CounterMelodyOptions = {
|
|
|
179
208
|
*/
|
|
180
209
|
declare function generateCounterMelody(opts: CounterMelodyOptions): NoteEvent[];
|
|
181
210
|
|
|
182
|
-
/**
|
|
211
|
+
/**
|
|
212
|
+
* The percussion voices the generator emits, as General MIDI note numbers.
|
|
213
|
+
*
|
|
214
|
+
* A {@link DrumHit} carries only its pitch, so splitting a kit across tracks —
|
|
215
|
+
* kick to one, snare to another — means comparing against these numbers. They
|
|
216
|
+
* are published so that comparison is a named constant covered by semver
|
|
217
|
+
* rather than a hard-coded 36.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* import { DRUM_NOTES, generateDrums } from '@libraz/libcantus';
|
|
222
|
+
* const hits = generateDrums({ bars: 1, bpm: 120, style: 'standard', section: 'verse', density: 0.5 });
|
|
223
|
+
* const kick = hits.filter((hit) => hit.pitch === DRUM_NOTES.kick);
|
|
224
|
+
* ```
|
|
225
|
+
* @category Composition
|
|
226
|
+
*/
|
|
227
|
+
declare const DRUM_NOTES: {
|
|
228
|
+
readonly kick: 36;
|
|
229
|
+
readonly snare: 38;
|
|
230
|
+
readonly sideStick: 37;
|
|
231
|
+
readonly handClap: 39;
|
|
232
|
+
readonly closedHiHat: 42;
|
|
233
|
+
readonly pedalHiHat: 44;
|
|
234
|
+
readonly openHiHat: 46;
|
|
235
|
+
readonly crash: 49;
|
|
236
|
+
readonly ride: 51;
|
|
237
|
+
readonly tambourine: 54;
|
|
238
|
+
readonly highTom: 50;
|
|
239
|
+
readonly midTom: 47;
|
|
240
|
+
readonly lowTom: 45;
|
|
241
|
+
readonly shaker: 82;
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* A percussion voice name, one key of {@link DRUM_NOTES}.
|
|
245
|
+
*
|
|
246
|
+
* @category Composition
|
|
247
|
+
*/
|
|
248
|
+
type DrumVoice = keyof typeof DRUM_NOTES;
|
|
249
|
+
/**
|
|
250
|
+
* The voice a percussion note number names.
|
|
251
|
+
*
|
|
252
|
+
* @param pitch The General MIDI note number.
|
|
253
|
+
* @returns The voice, or undefined for a note this generator never emits.
|
|
254
|
+
* @category Composition
|
|
255
|
+
*/
|
|
256
|
+
declare function drumVoiceOf(pitch: number): DrumVoice | undefined;
|
|
257
|
+
/**
|
|
258
|
+
* A single percussion onset.
|
|
259
|
+
*
|
|
260
|
+
* @category Composition
|
|
261
|
+
*/
|
|
183
262
|
type DrumHit = {
|
|
263
|
+
/** General MIDI note number; {@link drumVoiceOf} names it. */
|
|
184
264
|
pitch: number;
|
|
185
265
|
startBeat: number;
|
|
186
266
|
durationBeat: number;
|
|
187
267
|
velocity: number;
|
|
188
268
|
};
|
|
189
269
|
|
|
270
|
+
/** Every groove feel, in declaration order. */
|
|
271
|
+
declare const DRUM_FEELS: readonly ["straight", "swing", "shuffle"];
|
|
190
272
|
/** Groove feel controlling off-beat swing. */
|
|
191
|
-
type Feel =
|
|
192
|
-
/**
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
273
|
+
type Feel = (typeof DRUM_FEELS)[number];
|
|
274
|
+
/**
|
|
275
|
+
* Every public groove style, in declaration order. The type is derived from
|
|
276
|
+
* this list so the runtime guard and the type can never disagree.
|
|
277
|
+
*/
|
|
278
|
+
declare const GROOVE_STYLES: readonly ["standard", "funk", "shuffle", "bossa", "trap", "halftime", "breakbeat", "house", "synthpop"];
|
|
279
|
+
/**
|
|
280
|
+
* Public groove style identifiers.
|
|
281
|
+
*
|
|
282
|
+
* @category Composition
|
|
283
|
+
*/
|
|
284
|
+
type GrooveStyle = (typeof GROOVE_STYLES)[number];
|
|
285
|
+
/** Every public role, in declaration order. */
|
|
286
|
+
declare const DRUM_ROLES: readonly ["full", "ambient", "minimal", "fxOnly"];
|
|
287
|
+
/**
|
|
288
|
+
* Public role identifiers gating which voices are present.
|
|
289
|
+
*
|
|
290
|
+
* @category Composition
|
|
291
|
+
*/
|
|
292
|
+
type DrumRole = (typeof DRUM_ROLES)[number];
|
|
293
|
+
/** Every public section, in declaration order. */
|
|
294
|
+
declare const PUBLIC_SECTIONS: readonly ["intro", "verse", "prechorus", "chorus", "bridge", "outro"];
|
|
196
295
|
/** Public section identifiers. */
|
|
197
|
-
type PublicSection =
|
|
296
|
+
type PublicSection = (typeof PUBLIC_SECTIONS)[number];
|
|
198
297
|
|
|
199
298
|
/**
|
|
200
299
|
* Groove feel (the swing/straight rhythmic character) for {@link generateDrums}.
|
|
@@ -236,6 +335,12 @@ type EuclideanKick = {
|
|
|
236
335
|
* @category Composition
|
|
237
336
|
*/
|
|
238
337
|
type DrumsOptions = {
|
|
338
|
+
/**
|
|
339
|
+
* Number of bars to generate. Bars are four quarter-note beats long: the
|
|
340
|
+
* patterns are written for 4/4 and there is no meter option, so a `bars`
|
|
341
|
+
* count shared with a meter-aware generator such as
|
|
342
|
+
* {@link generateRhythm} only lines up when that generator is also in 4/4.
|
|
343
|
+
*/
|
|
239
344
|
bars: number;
|
|
240
345
|
bpm: number;
|
|
241
346
|
style: GrooveStyle;
|
|
@@ -244,12 +349,26 @@ type DrumsOptions = {
|
|
|
244
349
|
/**
|
|
245
350
|
* Replace the final bar with a fill.
|
|
246
351
|
*
|
|
352
|
+
* A pre-chorus leading into a chorus builds instead: the two-bar lift takes
|
|
353
|
+
* precedence over the fill, since the buildup already marks the phrase end.
|
|
354
|
+
* Set `nextSection` to anything but `'chorus'` to get the fill.
|
|
355
|
+
*
|
|
247
356
|
* @defaultValue false
|
|
248
357
|
*/
|
|
249
358
|
fills?: boolean;
|
|
250
359
|
feel?: GrooveFeel;
|
|
251
360
|
/**
|
|
252
|
-
* Voicing role
|
|
361
|
+
* Voicing role, from busiest to sparsest:
|
|
362
|
+
*
|
|
363
|
+
* - `'full'`: every voice, backbeat snare at full weight.
|
|
364
|
+
* - `'ambient'`: side-stick backbeat, ride instead of hi-hat.
|
|
365
|
+
* - `'minimal'`: side-stick backbeat quieter still, pedal hi-hat, no
|
|
366
|
+
* auxiliary percussion.
|
|
367
|
+
* - `'fxOnly'`: no kick, snare, ghost notes, timekeeping hi-hat, or fills —
|
|
368
|
+
* only the fx and auxiliary voices.
|
|
369
|
+
*
|
|
370
|
+
* The ordering holds in every style and section: a busier role never emits
|
|
371
|
+
* fewer or quieter voices than a sparser one.
|
|
253
372
|
*
|
|
254
373
|
* @defaultValue `'full'`
|
|
255
374
|
*/
|
|
@@ -286,8 +405,12 @@ type DrumsOptions = {
|
|
|
286
405
|
* overrides the kick with an evenly-spread Euclidean pattern. Output is fully
|
|
287
406
|
* determined by the options plus `seed`.
|
|
288
407
|
*
|
|
408
|
+
* The patterns are 4/4 only — backbeats, hi-hat subdivisions, and fills are all
|
|
409
|
+
* written against a four-beat bar — so beat positions are quarter notes and bar
|
|
410
|
+
* `n` starts at beat `4n`.
|
|
411
|
+
*
|
|
289
412
|
* @param opts Generation options.
|
|
290
|
-
* @returns Percussion onsets in
|
|
413
|
+
* @returns Percussion onsets in onset order, ties broken by pitch.
|
|
291
414
|
*
|
|
292
415
|
* @example
|
|
293
416
|
* ```ts
|
|
@@ -377,9 +500,12 @@ type HumanizeOptions = {
|
|
|
377
500
|
* const events = [{ pitch: 60, startBeat: 0, durationBeat: 1, velocity: 80 }];
|
|
378
501
|
* humanize(events, { seed: 1, timing: 0.03 }); // copies with jittered timing and accented velocity
|
|
379
502
|
* ```
|
|
503
|
+
* Notes with a zero or negative duration never sound and are dropped, so the
|
|
504
|
+
* result can be shorter than the input.
|
|
505
|
+
*
|
|
380
506
|
* @category Rhythm & Meter
|
|
381
507
|
*/
|
|
382
|
-
declare function humanize(events: NoteEvent[], opts?: HumanizeOptions): NoteEvent[];
|
|
508
|
+
declare function humanize(events: readonly NoteEvent[], opts?: HumanizeOptions): NoteEvent[];
|
|
383
509
|
/**
|
|
384
510
|
* The recorded feel at a single grid slot: an average timing deviation and velocity.
|
|
385
511
|
*
|
|
@@ -426,10 +552,12 @@ type GrooveTemplate = {
|
|
|
426
552
|
* @param events The (typically "groovy", human-played) events to analyze.
|
|
427
553
|
* @param ts The time signature, used to compute the bar length.
|
|
428
554
|
* @param subdivision Grid resolution: equal grid steps per quarter-note beat.
|
|
555
|
+
* Defaults to a sixteenth-note grid, which is where the timing deviations a
|
|
556
|
+
* template records — swing, push, drag — are audible.
|
|
429
557
|
* @returns The extracted groove template.
|
|
430
558
|
* @category Rhythm & Meter
|
|
431
559
|
*/
|
|
432
|
-
declare function extractGrooveTemplate(events: NoteEvent[], ts: TimeSignature, subdivision
|
|
560
|
+
declare function extractGrooveTemplate(events: readonly NoteEvent[], ts: TimeSignature, subdivision?: number): GrooveTemplate;
|
|
433
561
|
/**
|
|
434
562
|
* Apply a groove template to a set of (typically quantized) note events: each
|
|
435
563
|
* event is snapped to its grid slot and then offset by that slot's recorded
|
|
@@ -464,7 +592,7 @@ declare function extractGrooveTemplate(events: NoteEvent[], ts: TimeSignature, s
|
|
|
464
592
|
* ```
|
|
465
593
|
* @category Rhythm & Meter
|
|
466
594
|
*/
|
|
467
|
-
declare function applyGrooveTemplate(events: NoteEvent[], template: GrooveTemplate, ts: TimeSignature): NoteEvent[];
|
|
595
|
+
declare function applyGrooveTemplate(events: readonly NoteEvent[], template: GrooveTemplate, ts: TimeSignature): NoteEvent[];
|
|
468
596
|
|
|
469
597
|
/**
|
|
470
598
|
* Broad production style a progression preset suits.
|
|
@@ -486,10 +614,55 @@ type ProgFunction = 'loop' | 'tensionBuild' | 'cadenceStrong' | 'stable';
|
|
|
486
614
|
type ProgressionPreset = {
|
|
487
615
|
id: string;
|
|
488
616
|
name: string;
|
|
489
|
-
|
|
617
|
+
/**
|
|
618
|
+
* The chord roots, in order, as {@link ProgressionDegree} codes: 0..6 for the
|
|
619
|
+
* key's own scale degrees and {@link BORROWED_DEGREES} for the borrowed ones.
|
|
620
|
+
*/
|
|
621
|
+
degrees: ProgressionDegree[];
|
|
490
622
|
functional: ProgFunction;
|
|
491
623
|
styles: ProgStyle[];
|
|
492
624
|
};
|
|
625
|
+
/**
|
|
626
|
+
* The borrowed (non-diatonic) chord roots a preset can name, as their semitone
|
|
627
|
+
* offset above the tonic.
|
|
628
|
+
*
|
|
629
|
+
* Scale degrees 0..6 address the key's own chords; these codes continue the
|
|
630
|
+
* numbering for the chromatic chords a pop progression borrows, so a preset is
|
|
631
|
+
* one flat list of degree codes.
|
|
632
|
+
*
|
|
633
|
+
* @example
|
|
634
|
+
* ```ts
|
|
635
|
+
* import { BORROWED_DEGREES, generateProgression, majorKey } from '@libraz/libcantus';
|
|
636
|
+
* generateProgression({
|
|
637
|
+
* key: majorKey(0),
|
|
638
|
+
* style: 'rock',
|
|
639
|
+
* bars: 4,
|
|
640
|
+
* preset: { degrees: [0, BORROWED_DEGREES.bVII, 3, 0] },
|
|
641
|
+
* });
|
|
642
|
+
* ```
|
|
643
|
+
* @category Composition
|
|
644
|
+
*/
|
|
645
|
+
declare const BORROWED_DEGREES: {
|
|
646
|
+
/** Flat submediant: bVI. */
|
|
647
|
+
readonly bVI: 8;
|
|
648
|
+
/** Flat subtonic: bVII. */
|
|
649
|
+
readonly bVII: 10;
|
|
650
|
+
/** Flat mediant: bIII. */
|
|
651
|
+
readonly bIII: 11;
|
|
652
|
+
/** Minor subdominant borrowed from the parallel minor: iv. */
|
|
653
|
+
readonly iv: 12;
|
|
654
|
+
/** Neapolitan: bII. */
|
|
655
|
+
readonly bII: 13;
|
|
656
|
+
/** Sharp subdominant, the diminished #IV. */
|
|
657
|
+
readonly sharpIV: 14;
|
|
658
|
+
};
|
|
659
|
+
/**
|
|
660
|
+
* A chord root in a preset: a scale degree 0..6, or one of
|
|
661
|
+
* {@link BORROWED_DEGREES}.
|
|
662
|
+
*
|
|
663
|
+
* @category Composition
|
|
664
|
+
*/
|
|
665
|
+
type ProgressionDegree = number;
|
|
493
666
|
/**
|
|
494
667
|
* Options controlling {@link generateProgression}.
|
|
495
668
|
*
|
|
@@ -497,9 +670,21 @@ type ProgressionPreset = {
|
|
|
497
670
|
*/
|
|
498
671
|
type ProgressionOptions = {
|
|
499
672
|
key: KeyScale;
|
|
673
|
+
/**
|
|
674
|
+
* Which pool of built-in presets to choose from. Ignored when `preset` names
|
|
675
|
+
* the progression outright.
|
|
676
|
+
*/
|
|
500
677
|
style: ProgStyle;
|
|
501
678
|
bars: number;
|
|
679
|
+
/** Pick a specific built-in preset by id instead of choosing one by style. */
|
|
502
680
|
presetId?: string;
|
|
681
|
+
/**
|
|
682
|
+
* Use this progression rather than a built-in one. Only `degrees` is
|
|
683
|
+
* required; see {@link BORROWED_DEGREES} for the non-diatonic codes.
|
|
684
|
+
*/
|
|
685
|
+
preset?: Partial<ProgressionPreset> & {
|
|
686
|
+
degrees: ProgressionDegree[];
|
|
687
|
+
};
|
|
503
688
|
ext?: ChordQuality | 'auto';
|
|
504
689
|
reharmonize?: boolean;
|
|
505
690
|
/**
|
|
@@ -521,23 +706,44 @@ declare function progressions(): ProgressionPreset[];
|
|
|
521
706
|
* @category Composition
|
|
522
707
|
*/
|
|
523
708
|
declare function progressionsByStyle(style: ProgStyle): ProgressionPreset[];
|
|
709
|
+
/**
|
|
710
|
+
* The preset {@link generateProgression} would choose for a style and seed.
|
|
711
|
+
*
|
|
712
|
+
* The choice is otherwise invisible: the generator returns chords, not the
|
|
713
|
+
* preset it drew them from, so a caller who wants to show or reproduce it has
|
|
714
|
+
* no way to name it.
|
|
715
|
+
*
|
|
716
|
+
* @param style The style pool to choose from.
|
|
717
|
+
* @param seed The same seed the generator would be given.
|
|
718
|
+
* @returns The preset that seed selects.
|
|
719
|
+
* @throws If no preset claims the style.
|
|
720
|
+
* @example
|
|
721
|
+
* ```ts
|
|
722
|
+
* import { pickProgressionPreset } from '@libraz/libcantus';
|
|
723
|
+
* pickProgressionPreset('dance', 3).name;
|
|
724
|
+
* ```
|
|
725
|
+
* @category Composition
|
|
726
|
+
*/
|
|
727
|
+
declare function pickProgressionPreset(style: ProgStyle, seed?: number): ProgressionPreset;
|
|
524
728
|
/**
|
|
525
729
|
* Generate a chord progression laid out one chord per bar.
|
|
526
730
|
*
|
|
527
731
|
* A preset is chosen by `presetId` when given, otherwise deterministically from
|
|
528
|
-
* the presets matching `style`, seeded by `seed`. An unknown `presetId
|
|
529
|
-
* caller error and throws rather than silently
|
|
530
|
-
* The preset's degrees cycle to
|
|
732
|
+
* the presets matching `style`, seeded by `seed`. An unknown `presetId`, or a
|
|
733
|
+
* `style` no preset claims, is a caller error and throws rather than silently
|
|
734
|
+
* falling back to a random preset. The preset's degrees cycle to
|
|
531
735
|
* fill `bars`; each bar is four beats, so `startBeat` is `barIndex * 4`. Chord
|
|
532
736
|
* roots come from the key's diatonic scale-degree mapping. When `ext` is
|
|
533
737
|
* omitted or `'auto'`, each chord takes its diatonic triad quality; otherwise
|
|
534
|
-
* `ext` is forced on every chord
|
|
738
|
+
* `ext` is forced on every chord — except a chord replaced by `reharmonize`,
|
|
739
|
+
* which is a secondary dominant and is therefore always a `dom7`; those carry
|
|
740
|
+
* `secondaryDominant: true`. When `reharmonize` is set, some chords are
|
|
535
741
|
* deterministically replaced with the secondary dominant (V7) of the following
|
|
536
742
|
* chord, flagged with `secondaryDominant`.
|
|
537
743
|
*
|
|
538
744
|
* @param opts Generation options.
|
|
539
745
|
* @returns One chord per bar in timeline order.
|
|
540
|
-
* @throws If `presetId`
|
|
746
|
+
* @throws If `presetId` matches no built-in preset, or `style` matches none.
|
|
541
747
|
*
|
|
542
748
|
* @example
|
|
543
749
|
* ```ts
|
|
@@ -561,15 +767,72 @@ type MelodyNote = NoteEvent;
|
|
|
561
767
|
*
|
|
562
768
|
* @category Reharmonization
|
|
563
769
|
*/
|
|
770
|
+
type HarmonizePlacement = {
|
|
771
|
+
/**
|
|
772
|
+
* Search a range of transpositions and keep the best-fitting one. The result
|
|
773
|
+
* reports the shift it chose in `transposeSemitones`.
|
|
774
|
+
*
|
|
775
|
+
* @defaultValue false
|
|
776
|
+
*/
|
|
777
|
+
transposeSearch: boolean;
|
|
778
|
+
/**
|
|
779
|
+
* Search octave placements as well, so a melody written too high or too low
|
|
780
|
+
* is moved into a comfortable register.
|
|
781
|
+
*
|
|
782
|
+
* @defaultValue false
|
|
783
|
+
*/
|
|
784
|
+
octaveSearch: boolean;
|
|
785
|
+
};
|
|
786
|
+
/**
|
|
787
|
+
* Options controlling {@link harmonizeMelody}.
|
|
788
|
+
*
|
|
789
|
+
* Only `melody` is required; every other knob has the default a first call
|
|
790
|
+
* wants.
|
|
791
|
+
*
|
|
792
|
+
* @category Reharmonization
|
|
793
|
+
*/
|
|
564
794
|
type HarmonizeOptions = {
|
|
565
|
-
melody
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
795
|
+
/** The melody to harmonize, in ascending onset order. */
|
|
796
|
+
melody: readonly MelodyNote[];
|
|
797
|
+
/**
|
|
798
|
+
* The key to harmonize in, or `'infer'` to estimate it from the melody's
|
|
799
|
+
* pitch-class weighting — which is what a caller who has only a melody
|
|
800
|
+
* wants, and so the default.
|
|
801
|
+
*
|
|
802
|
+
* @defaultValue `'infer'`
|
|
803
|
+
*/
|
|
804
|
+
key?: KeyScale | 'infer';
|
|
805
|
+
/**
|
|
806
|
+
* Length of each chord slot in beats. Any positive value is honoured, as in
|
|
807
|
+
* {@link chordTimelineFromNotes}; a value fine enough to make the search
|
|
808
|
+
* explode is rejected by the generation budget rather than rounded up.
|
|
809
|
+
*
|
|
810
|
+
* @defaultValue 2
|
|
811
|
+
*/
|
|
812
|
+
harmonicRhythm?: number;
|
|
813
|
+
/**
|
|
814
|
+
* Time signature used to weight metric accents; defaults to 4/4. A waltz or
|
|
815
|
+
* a jig harmonized against a 4/4 accent grid gets its chords placed on the
|
|
816
|
+
* wrong beats, and the error accumulates bar by bar.
|
|
817
|
+
*
|
|
818
|
+
* @defaultValue `4/4`
|
|
819
|
+
*/
|
|
820
|
+
ts?: TimeSignature;
|
|
821
|
+
/**
|
|
822
|
+
* How far beyond the key's own triads the chord vocabulary reaches:
|
|
823
|
+
* `'diatonic'` uses only them, `'secondaryDominant'` adds the dominants that
|
|
824
|
+
* tonicize each degree, and `'borrowed'` adds the parallel mode's chords too.
|
|
825
|
+
*
|
|
826
|
+
* @defaultValue `'diatonic'`
|
|
827
|
+
*/
|
|
828
|
+
reharmonize?: 'diatonic' | 'secondaryDominant' | 'borrowed';
|
|
829
|
+
/**
|
|
830
|
+
* Whether to search transpositions and octave placements for the melody.
|
|
831
|
+
* Both are off by default, so the melody is harmonized where it was written.
|
|
832
|
+
*
|
|
833
|
+
* @defaultValue both false
|
|
834
|
+
*/
|
|
835
|
+
placement?: HarmonizePlacement;
|
|
573
836
|
/**
|
|
574
837
|
* Seed for the deterministic tie-break perturbation.
|
|
575
838
|
*
|
|
@@ -603,26 +866,23 @@ type HarmonizeResult = {
|
|
|
603
866
|
* ties toward placements that keep the melody in a comfortable register.
|
|
604
867
|
*
|
|
605
868
|
* The `seed` drives a deterministic tie-break only: it perturbs candidates by a
|
|
606
|
-
* magnitude far below any real cost difference (see
|
|
869
|
+
* magnitude far below any real cost difference (see `TIE_BREAK_JITTER`),
|
|
607
870
|
* so it can decide between chords or paths of otherwise-equal cost but never
|
|
608
871
|
* overrides melody fit or functional flow. For a well-determined melody the
|
|
609
872
|
* result is identical across seeds; the same seed always yields the same result.
|
|
610
873
|
*
|
|
611
|
-
* @param opts
|
|
612
|
-
* strength,
|
|
874
|
+
* @param opts The melody and, optionally, the key, harmonic rhythm,
|
|
875
|
+
* reharmonization strength, placement search, meter, and seed. Only `melody`
|
|
876
|
+
* is required.
|
|
613
877
|
* @returns The chosen transpose, key, chord path, and per-note roles.
|
|
614
878
|
* @example
|
|
615
879
|
* ```ts
|
|
616
|
-
* import { harmonizeMelody
|
|
880
|
+
* import { harmonizeMelody } from '@libraz/libcantus';
|
|
617
881
|
* const result = harmonizeMelody({
|
|
618
882
|
* melody: [
|
|
619
883
|
* { pitch: 60, startBeat: 0, durationBeat: 1 },
|
|
620
884
|
* { pitch: 64, startBeat: 1, durationBeat: 1 },
|
|
621
885
|
* ],
|
|
622
|
-
* key: majorKey(0),
|
|
623
|
-
* harmonicRhythm: 1,
|
|
624
|
-
* reharmonize: 'diatonic',
|
|
625
|
-
* placement: { transposeSearch: false, octaveSearch: false },
|
|
626
886
|
* });
|
|
627
887
|
* result.chords; // one ChordSpan per harmonic-rhythm segment
|
|
628
888
|
* ```
|
|
@@ -668,7 +928,15 @@ type MotifContour = 'arch' | 'ascending' | 'descending' | 'wave';
|
|
|
668
928
|
type MotifOptions = {
|
|
669
929
|
key: KeyScale;
|
|
670
930
|
chord?: Chord | null;
|
|
931
|
+
/** Length of the motif in bars of `ts`. */
|
|
671
932
|
bars: number;
|
|
933
|
+
/**
|
|
934
|
+
* Meter the bars are counted in. It sets the bar length, so a motif shares a
|
|
935
|
+
* bar grid with the other generators instead of assuming four beats.
|
|
936
|
+
*
|
|
937
|
+
* @defaultValue 4/4
|
|
938
|
+
*/
|
|
939
|
+
ts?: TimeSignature;
|
|
672
940
|
/**
|
|
673
941
|
* Melodic contour shape the line follows.
|
|
674
942
|
*
|
|
@@ -713,6 +981,23 @@ type MotifOptions = {
|
|
|
713
981
|
* @category Composition
|
|
714
982
|
*/
|
|
715
983
|
declare function generateMotif(opts: MotifOptions): MotifCell;
|
|
984
|
+
/**
|
|
985
|
+
* Turn a motif cell into note events.
|
|
986
|
+
*
|
|
987
|
+
* A {@link MotifNote} already carries the {@link NoteEvent} fields, but a cell
|
|
988
|
+
* wraps them in an object; this unwraps it, so a motif can be humanized,
|
|
989
|
+
* grooved, or written out like any other line.
|
|
990
|
+
*
|
|
991
|
+
* @param cell The motif to convert.
|
|
992
|
+
* @returns The cell's notes, copied, in the order they are stored.
|
|
993
|
+
* @example
|
|
994
|
+
* ```ts
|
|
995
|
+
* import { generateMotif, humanize, majorKey, motifToNoteEvents } from '@libraz/libcantus';
|
|
996
|
+
* humanize(motifToNoteEvents(generateMotif({ key: majorKey(0), bars: 2 })));
|
|
997
|
+
* ```
|
|
998
|
+
* @category Composition
|
|
999
|
+
*/
|
|
1000
|
+
declare function motifToNoteEvents(cell: MotifCell): NoteEvent[];
|
|
716
1001
|
/**
|
|
717
1002
|
* Apply a transformation to a motif cell.
|
|
718
1003
|
*
|
|
@@ -731,6 +1016,7 @@ declare function generateMotif(opts: MotifOptions): MotifCell;
|
|
|
731
1016
|
* @param key Key context for the diatonic transforms; without it,
|
|
732
1017
|
* `transposeDiatonic` and `sequence` shift chromatically by semitones.
|
|
733
1018
|
* @returns The transformed cell.
|
|
1019
|
+
* @throws If a transformed pitch would fall outside the MIDI range 0..127.
|
|
734
1020
|
*
|
|
735
1021
|
* @example
|
|
736
1022
|
* ```ts
|
|
@@ -752,7 +1038,8 @@ declare function transformMotif(cell: MotifCell, t: MotifTransform, amount?: num
|
|
|
752
1038
|
* @param cell The source motif.
|
|
753
1039
|
* @param timeline Chord segments to snap against.
|
|
754
1040
|
* @param key Key context (used to keep snapped pitches sensible).
|
|
755
|
-
* @param bars Number of
|
|
1041
|
+
* @param bars Number of bars to fill.
|
|
1042
|
+
* @param ts Meter the bars are counted in; defaults to 4/4.
|
|
756
1043
|
* @returns The developed, harmony-aware cell.
|
|
757
1044
|
*
|
|
758
1045
|
* @example
|
|
@@ -765,7 +1052,7 @@ declare function transformMotif(cell: MotifCell, t: MotifTransform, amount?: num
|
|
|
765
1052
|
*
|
|
766
1053
|
* @category Composition
|
|
767
1054
|
*/
|
|
768
|
-
declare function developMotif(cell: MotifCell, timeline: ChordTimeline, key: KeyScale, bars: number): MotifCell;
|
|
1055
|
+
declare function developMotif(cell: MotifCell, timeline: ChordTimeline, key: KeyScale, bars: number, ts?: TimeSignature): MotifCell;
|
|
769
1056
|
|
|
770
1057
|
/**
|
|
771
1058
|
* Reharmonization: chord substitution, modal-interchange palettes, and negative
|
|
@@ -781,7 +1068,7 @@ declare function developMotif(cell: MotifCell, timeline: ChordTimeline, key: Key
|
|
|
781
1068
|
*
|
|
782
1069
|
* @category Reharmonization
|
|
783
1070
|
*/
|
|
784
|
-
type SubstitutionType = 'tritone' | 'relative' | 'borrowed' | '
|
|
1071
|
+
type SubstitutionType = 'tritone' | 'relative' | 'borrowed' | 'chromaticMediant' | 'secondaryDominant';
|
|
785
1072
|
/**
|
|
786
1073
|
* A proposed chord substitution with its relationship, numeral, and function.
|
|
787
1074
|
*
|
|
@@ -813,11 +1100,11 @@ type SubstituteOptions = {
|
|
|
813
1100
|
* original chord and each other:
|
|
814
1101
|
*
|
|
815
1102
|
* - `tritone`: for a dominant-type chord, the dominant seventh a tritone away.
|
|
816
|
-
* - `
|
|
1103
|
+
* - `secondaryDominant`: for a stable target, the dominant seventh a fifth
|
|
817
1104
|
* above its root (tonicizing it).
|
|
818
1105
|
* - `relative`: a diatonic triad a third away that shares two common tones.
|
|
819
1106
|
* - `borrowed`: a triad from the parallel mode with the same harmonic function.
|
|
820
|
-
* - `
|
|
1107
|
+
* - `chromaticMediant`: a major/minor triad a third away sharing one common
|
|
821
1108
|
* tone.
|
|
822
1109
|
*
|
|
823
1110
|
* Each result carries its Roman numeral and harmonic function in `key`. When
|
|
@@ -906,6 +1193,27 @@ type RhythmEvent = {
|
|
|
906
1193
|
/** Duration in quarter-note beats, extending to the next onset. */
|
|
907
1194
|
duration: number;
|
|
908
1195
|
};
|
|
1196
|
+
/**
|
|
1197
|
+
* Turn rhythm events into note events at a fixed pitch.
|
|
1198
|
+
*
|
|
1199
|
+
* {@link RhythmEvent} names its fields `position`/`duration` because a rhythm
|
|
1200
|
+
* has no pitch; every other generator in the library speaks {@link NoteEvent}.
|
|
1201
|
+
* This is the bridge, so a generated rhythm can be humanized, grooved, or
|
|
1202
|
+
* written out like any other line.
|
|
1203
|
+
*
|
|
1204
|
+
* @param events The rhythm events to convert.
|
|
1205
|
+
* @param pitch The MIDI pitch to give every note.
|
|
1206
|
+
* @param velocity Velocity for every note; defaults to a mezzo-forte 96.
|
|
1207
|
+
* @returns The note events, in the order given.
|
|
1208
|
+
* @example
|
|
1209
|
+
* ```ts
|
|
1210
|
+
* import { generateRhythm, humanize, rhythmToNoteEvents } from '@libraz/libcantus';
|
|
1211
|
+
* const rhythm = generateRhythm({ numerator: 4, denominator: 4 }, { bars: 2 });
|
|
1212
|
+
* humanize(rhythmToNoteEvents(rhythm, 38));
|
|
1213
|
+
* ```
|
|
1214
|
+
* @category Rhythm & Meter
|
|
1215
|
+
*/
|
|
1216
|
+
declare function rhythmToNoteEvents(events: RhythmEvent[], pitch: number, velocity?: number): NoteEvent[];
|
|
909
1217
|
/**
|
|
910
1218
|
* Options controlling {@link generateRhythm}.
|
|
911
1219
|
*
|
|
@@ -983,4 +1291,4 @@ declare function generateRhythm(ts: TimeSignature, opts?: RhythmOptions): Rhythm
|
|
|
983
1291
|
*/
|
|
984
1292
|
declare function rhythmDensity(events: RhythmEvent[], ts: TimeSignature): number;
|
|
985
1293
|
|
|
986
|
-
export { type BassLineOptions, type BassSegment, type BassStyle, type BorrowedChord, type CounterMelodyOptions, type DrumHit, type DrumRole, type DrumsOptions, type EuclideanKick, type GrooveFeel, type GrooveSlot, type GrooveStyle, type GrooveTemplate, type HarmonizeOptions, type HarmonizeResult, type HumanizeOptions, type MelodyNote, type MotifCell, type MotifContour, type MotifNote, type MotifOptions, type MotifTransform, type ProgFunction, type ProgStyle, type ProgressionOptions, type ProgressionPreset, type RhythmEvent, type RhythmOptions, type Section, type SubstituteOptions, type Substitution, type SubstitutionType, applyGrooveTemplate, developMotif, extractGrooveTemplate, generateBassLine, generateCounterMelody, generateDrums, generateMotif, generateProgression, generateRhythm, harmonizeMelody, humanize, modalInterchangePalette, negativeHarmonyMirror, onsetWeightCurve, progressions, progressionsByStyle, rhythmDensity, substituteChord, transformMotif };
|
|
1294
|
+
export { BASS_STYLES, BORROWED_DEGREES, type BassLineOptions, type BassSegment, type BassStyle, type BorrowedChord, BorrowedSource, Chord as ChordData, ChordQuality, ChordSegment, ChordSpan, ChordTimeline, type CounterMelodyOptions, DRUM_NOTES, type DrumHit, type DrumRole, type DrumVoice, type DrumsOptions, type EuclideanKick, type GrooveFeel, type GrooveSlot, type GrooveStyle, type GrooveTemplate, HarmonicFunction, type HarmonizeOptions, type HarmonizePlacement, type HarmonizeResult, HarmonyRole, type HumanizeOptions, KeyScale, type MelodyNote, type MotifCell, type MotifContour, type MotifNote, type MotifOptions, type MotifTransform, NoteEvent, type ProgFunction, type ProgStyle, type ProgressionDegree, type ProgressionOptions, type ProgressionPreset, type RhythmEvent, type RhythmOptions, type Section, type SubstituteOptions, type Substitution, type SubstitutionType, TimeSignature, applyGrooveTemplate, developMotif, drumVoiceOf, extractGrooveTemplate, generateBassLine, generateCounterMelody, generateDrums, generateMotif, generateProgression, generateRhythm, harmonizeMelody, humanize, modalInterchangePalette, motifToNoteEvents, negativeHarmonyMirror, onsetWeightCurve, pickProgressionPreset, progressions, progressionsByStyle, rhythmDensity, rhythmToNoteEvents, substituteChord, transformMotif };
|