@libraz/libcantus 0.9.3 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -20
- package/README_ja.md +268 -0
- package/dist/analyze/index.cjs +39 -1947
- package/dist/analyze/index.cjs.map +1 -1
- package/dist/analyze/index.d.cts +161 -91
- package/dist/analyze/index.d.ts +161 -91
- package/dist/analyze/index.js +19 -8
- package/dist/chunk-2A2QMA74.cjs +261 -0
- package/dist/chunk-2A2QMA74.cjs.map +1 -0
- package/dist/chunk-2PTFGVD7.js +261 -0
- package/dist/chunk-2PTFGVD7.js.map +1 -0
- package/dist/chunk-357ZDPVU.cjs +162 -0
- package/dist/chunk-357ZDPVU.cjs.map +1 -0
- package/dist/chunk-3KX76RLG.js +1548 -0
- package/dist/chunk-3KX76RLG.js.map +1 -0
- package/dist/chunk-4VZ5MZAM.cjs +889 -0
- package/dist/chunk-4VZ5MZAM.cjs.map +1 -0
- package/dist/{chunk-C5XYKUVG.js → chunk-7EONYVI5.js} +471 -171
- package/dist/chunk-7EONYVI5.js.map +1 -0
- package/dist/{chunk-IT2O4XFE.js → chunk-7JEP3MFY.js} +42 -34
- package/dist/chunk-7JEP3MFY.js.map +1 -0
- package/dist/{chunk-4MHA432G.js → chunk-AID75RN3.js} +572 -250
- package/dist/chunk-AID75RN3.js.map +1 -0
- package/dist/chunk-BSLTLGM3.cjs +497 -0
- package/dist/chunk-BSLTLGM3.cjs.map +1 -0
- package/dist/chunk-CU6VG2YM.cjs +109 -0
- package/dist/chunk-CU6VG2YM.cjs.map +1 -0
- package/dist/{chunk-EH6EM37U.js → chunk-DZMHIGI4.js} +81 -59
- package/dist/chunk-DZMHIGI4.js.map +1 -0
- package/dist/{chunk-AKLYPWIN.js → chunk-EDOTEABK.js} +45 -19
- package/dist/chunk-EDOTEABK.js.map +1 -0
- package/dist/{chunk-2ZWMSJH6.js → chunk-HN2OEUN2.js} +7 -4
- package/dist/chunk-HN2OEUN2.js.map +1 -0
- package/dist/{chunk-MIWO425M.js → chunk-KBTTEX7Q.js} +128 -43
- package/dist/chunk-KBTTEX7Q.js.map +1 -0
- package/dist/chunk-KQN2ZYND.cjs +724 -0
- package/dist/chunk-KQN2ZYND.cjs.map +1 -0
- package/dist/chunk-MPTVJIVG.cjs +3176 -0
- package/dist/chunk-MPTVJIVG.cjs.map +1 -0
- package/dist/chunk-MTMZTMWM.cjs +53 -0
- package/dist/chunk-MTMZTMWM.cjs.map +1 -0
- package/dist/{chunk-CHMXELDS.js → chunk-NNB67XA2.js} +372 -197
- package/dist/chunk-NNB67XA2.js.map +1 -0
- package/dist/chunk-OL3IHHSJ.cjs +1204 -0
- package/dist/chunk-OL3IHHSJ.cjs.map +1 -0
- package/dist/chunk-PI3UXRWK.cjs +528 -0
- package/dist/chunk-PI3UXRWK.cjs.map +1 -0
- package/dist/chunk-R2VVFAIN.js +528 -0
- package/dist/chunk-R2VVFAIN.js.map +1 -0
- package/dist/chunk-T64C7ZD7.cjs +1 -0
- package/dist/chunk-T64C7ZD7.cjs.map +1 -0
- package/dist/chunk-WFDXOLUB.cjs +337 -0
- package/dist/chunk-WFDXOLUB.cjs.map +1 -0
- package/dist/chunk-WTAN4ACG.cjs +1548 -0
- package/dist/chunk-WTAN4ACG.cjs.map +1 -0
- package/dist/chunk-YFJXS3AU.cjs +33 -0
- package/dist/chunk-YFJXS3AU.cjs.map +1 -0
- package/dist/{chunk-GOAW4VYL.js → chunk-YUE6TJ4M.js} +315 -145
- package/dist/chunk-YUE6TJ4M.js.map +1 -0
- package/dist/{chunk-62QZKCJQ.js → chunk-ZGLJM4A4.js} +10 -6
- package/dist/chunk-ZGLJM4A4.js.map +1 -0
- package/dist/core/index.cjs +140 -647
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +313 -41
- package/dist/core/index.d.ts +313 -41
- package/dist/core/index.js +64 -16
- package/dist/{function-DVH4Eusr.d.ts → function-CxixTB02.d.cts} +122 -10
- package/dist/{function-DYt4iKsn.d.cts → function-DTCt675z.d.ts} +122 -10
- package/dist/generate/index.cjs +28 -4085
- package/dist/generate/index.cjs.map +1 -1
- package/dist/generate/index.d.cts +374 -66
- package/dist/generate/index.d.ts +374 -66
- package/dist/generate/index.js +23 -9
- package/dist/{index-Jc0Ryi79.d.ts → index-B2Ulxxpo.d.cts} +21 -5
- package/dist/{index-CpOsP1y9.d.cts → index-BkYJ0xMq.d.cts} +18 -17
- package/dist/{index-CxqBQtH1.d.cts → index-BuaB-ypt.d.ts} +21 -5
- package/dist/index-CAN7v-kw.d.ts +199 -0
- package/dist/{index-Bt4tOUD9.d.ts → index-COw1Ky9g.d.ts} +93 -8
- package/dist/{index-Dikst44v.d.cts → index-Cfx8xgH0.d.ts} +14 -11
- package/dist/{index-DxvARIP2.d.ts → index-DRtIhlJj.d.ts} +18 -17
- 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-alrRninU.d.cts +199 -0
- package/dist/{index-BNlGP86A.d.cts → index-oTQbYYIs.d.cts} +93 -8
- package/dist/index-tR9jTn26.d.cts +275 -0
- package/dist/index-tR9jTn26.d.ts +275 -0
- package/dist/{index-Bg5dYMmZ.d.ts → index-x2vcsduE.d.cts} +14 -11
- package/dist/index.cjs +429 -7383
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +121 -27
- package/dist/model/index.cjs +8 -2562
- package/dist/model/index.cjs.map +1 -1
- package/dist/model/index.d.cts +471 -81
- package/dist/model/index.d.ts +471 -81
- package/dist/model/index.js +6 -7
- package/dist/styled-Bl0ZK28h.d.ts +543 -0
- package/dist/styled-Crv6SA4S.d.cts +543 -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 +34 -13
- 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 +0 -202
- 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 +0 -924
- 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,160 +0,0 @@
|
|
|
1
|
-
import { hasHit } from './euclid.js';
|
|
2
|
-
import type { DrumStyle, SectionType } from './internal.js';
|
|
3
|
-
import type { DrumRng } from './rng.js';
|
|
4
|
-
|
|
5
|
-
/** Kick presence flags across the eight 8th-note slots of a bar. */
|
|
6
|
-
export type KickPattern = {
|
|
7
|
-
beat1: boolean;
|
|
8
|
-
beat1and: boolean;
|
|
9
|
-
beat2: boolean;
|
|
10
|
-
beat2and: boolean;
|
|
11
|
-
beat3: boolean;
|
|
12
|
-
beat3and: boolean;
|
|
13
|
-
beat4: boolean;
|
|
14
|
-
beat4and: boolean;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const EMPTY: KickPattern = {
|
|
18
|
-
beat1: false,
|
|
19
|
-
beat1and: false,
|
|
20
|
-
beat2: false,
|
|
21
|
-
beat2and: false,
|
|
22
|
-
beat3: false,
|
|
23
|
-
beat3and: false,
|
|
24
|
-
beat4: false,
|
|
25
|
-
beat4and: false,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Whether a pre-chorus bar sits in the two-bar lift into the chorus.
|
|
30
|
-
*
|
|
31
|
-
* @param section Current section.
|
|
32
|
-
* @param bar Bar index within the section.
|
|
33
|
-
* @param sectionBars Total bars in the section.
|
|
34
|
-
* @param nextIsChorus Whether the following section is a chorus.
|
|
35
|
-
*/
|
|
36
|
-
export function isInPreChorusLift(
|
|
37
|
-
section: SectionType,
|
|
38
|
-
bar: number,
|
|
39
|
-
sectionBars: number,
|
|
40
|
-
nextIsChorus: boolean,
|
|
41
|
-
): boolean {
|
|
42
|
-
if (section !== 'b' || !nextIsChorus || sectionBars < 3) {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
return bar >= sectionBars - 2;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Convert a 16-step euclidean bitmask into an 8th-slot kick pattern. */
|
|
49
|
-
export function euclideanToKickPattern(mask: number): KickPattern {
|
|
50
|
-
const slot = (step: number) => hasHit(mask, step) || hasHit(mask, (step + 15) % 16);
|
|
51
|
-
return {
|
|
52
|
-
beat1: slot(0),
|
|
53
|
-
beat1and: slot(2),
|
|
54
|
-
beat2: slot(4),
|
|
55
|
-
beat2and: slot(6),
|
|
56
|
-
beat3: slot(8),
|
|
57
|
-
beat3and: slot(10),
|
|
58
|
-
beat4: slot(12),
|
|
59
|
-
beat4and: slot(14),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Build a section- and style-aware kick pattern.
|
|
65
|
-
*
|
|
66
|
-
* @param section Current section.
|
|
67
|
-
* @param style Internal drum style.
|
|
68
|
-
* @param bar Bar index (drives variation for a few styles).
|
|
69
|
-
* @param rng Deterministic PRNG for probabilistic accents.
|
|
70
|
-
*/
|
|
71
|
-
export function getKickPattern(
|
|
72
|
-
section: SectionType,
|
|
73
|
-
style: DrumStyle,
|
|
74
|
-
bar: number,
|
|
75
|
-
rng: DrumRng,
|
|
76
|
-
): KickPattern {
|
|
77
|
-
const p: KickPattern = { ...EMPTY };
|
|
78
|
-
|
|
79
|
-
if (section === 'outro') {
|
|
80
|
-
p.beat1 = true;
|
|
81
|
-
p.beat3 = true;
|
|
82
|
-
return p;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
switch (style) {
|
|
86
|
-
case 'sparse':
|
|
87
|
-
p.beat1 = true;
|
|
88
|
-
if (section === 'chorus' && bar % 2 === 1) {
|
|
89
|
-
p.beat3 = true;
|
|
90
|
-
}
|
|
91
|
-
break;
|
|
92
|
-
|
|
93
|
-
case 'fourOnFloor':
|
|
94
|
-
p.beat1 = p.beat2 = p.beat3 = p.beat4 = true;
|
|
95
|
-
if (section === 'chorus' && rng.prob(0.2)) {
|
|
96
|
-
p.beat2and = true;
|
|
97
|
-
}
|
|
98
|
-
break;
|
|
99
|
-
|
|
100
|
-
case 'upbeat':
|
|
101
|
-
p.beat1 = true;
|
|
102
|
-
p.beat3 = true;
|
|
103
|
-
if (section === 'b' || section === 'chorus') {
|
|
104
|
-
p.beat2and = rng.prob(0.7);
|
|
105
|
-
}
|
|
106
|
-
if (section === 'chorus') {
|
|
107
|
-
p.beat4and = rng.prob(0.6);
|
|
108
|
-
}
|
|
109
|
-
break;
|
|
110
|
-
|
|
111
|
-
case 'rock':
|
|
112
|
-
p.beat1 = true;
|
|
113
|
-
p.beat3 = true;
|
|
114
|
-
if (section === 'chorus') {
|
|
115
|
-
p.beat2and = rng.prob(0.65);
|
|
116
|
-
p.beat4and = rng.prob(0.4);
|
|
117
|
-
} else if (section === 'b') {
|
|
118
|
-
p.beat2and = rng.prob(0.3);
|
|
119
|
-
}
|
|
120
|
-
break;
|
|
121
|
-
|
|
122
|
-
case 'synth':
|
|
123
|
-
p.beat1 = true;
|
|
124
|
-
p.beat3 = true;
|
|
125
|
-
if (section === 'b' || section === 'chorus') {
|
|
126
|
-
p.beat2and = rng.prob(0.75);
|
|
127
|
-
}
|
|
128
|
-
if (section === 'chorus') {
|
|
129
|
-
p.beat4and = rng.prob(0.65);
|
|
130
|
-
}
|
|
131
|
-
break;
|
|
132
|
-
|
|
133
|
-
case 'trap':
|
|
134
|
-
p.beat1 = true;
|
|
135
|
-
p.beat2and = rng.prob(0.8);
|
|
136
|
-
p.beat3 = rng.prob(0.3);
|
|
137
|
-
p.beat4and = rng.prob(0.7);
|
|
138
|
-
break;
|
|
139
|
-
|
|
140
|
-
case 'latin':
|
|
141
|
-
p.beat1 = true;
|
|
142
|
-
p.beat2and = true;
|
|
143
|
-
p.beat3 = true;
|
|
144
|
-
p.beat4and = rng.prob(0.5);
|
|
145
|
-
break;
|
|
146
|
-
|
|
147
|
-
default:
|
|
148
|
-
p.beat1 = true;
|
|
149
|
-
p.beat3 = true;
|
|
150
|
-
if (section === 'b') {
|
|
151
|
-
p.beat2and = rng.prob(0.5);
|
|
152
|
-
} else if (section === 'chorus') {
|
|
153
|
-
p.beat2and = rng.prob(0.55);
|
|
154
|
-
p.beat4and = rng.prob(0.35);
|
|
155
|
-
}
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return p;
|
|
160
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { HH_16TH_BPM_THRESHOLD } from './hihat.js';
|
|
2
|
-
import type { HitList } from './hit.js';
|
|
3
|
-
import type { DrumRole, SectionType } from './internal.js';
|
|
4
|
-
import { EIGHTH, GM, PercMoodCategory, SIXTEENTH, sectionIndex } from './internal.js';
|
|
5
|
-
import type { DrumRng } from './rng.js';
|
|
6
|
-
|
|
7
|
-
/** Enabled auxiliary percussion voices for a section. */
|
|
8
|
-
export type PercussionConfig = {
|
|
9
|
-
tambourine: boolean;
|
|
10
|
-
shaker: boolean;
|
|
11
|
-
handclap: boolean;
|
|
12
|
-
shaker16th: boolean;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
type PercActivation = [tambourine: boolean, shaker: boolean, handclap: boolean];
|
|
16
|
-
|
|
17
|
-
// Percussion activation per [mood category][section index]. Columns:
|
|
18
|
-
// intro, a, b, chorus, bridge, interlude, outro, chant, mixbreak.
|
|
19
|
-
const F: PercActivation = [false, false, false];
|
|
20
|
-
const PERC_TABLE: PercActivation[][] = [
|
|
21
|
-
/* calm */ [F, F, F, F, F, F, F, F, F],
|
|
22
|
-
/* std */ [F, F, [false, true, false], [true, false, true], F, F, F, F, [true, false, true]],
|
|
23
|
-
/* ener */ [
|
|
24
|
-
F,
|
|
25
|
-
[false, true, false],
|
|
26
|
-
[false, true, false],
|
|
27
|
-
[true, true, true],
|
|
28
|
-
F,
|
|
29
|
-
F,
|
|
30
|
-
F,
|
|
31
|
-
F,
|
|
32
|
-
[true, true, true],
|
|
33
|
-
],
|
|
34
|
-
/* idol */ [
|
|
35
|
-
F,
|
|
36
|
-
[false, true, false],
|
|
37
|
-
[false, true, false],
|
|
38
|
-
[true, true, true],
|
|
39
|
-
F,
|
|
40
|
-
F,
|
|
41
|
-
F,
|
|
42
|
-
F,
|
|
43
|
-
[true, true, true],
|
|
44
|
-
],
|
|
45
|
-
/* rock */ [F, F, F, [false, false, true], F, F, F, F, [false, false, true]],
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
/** Resolve which auxiliary percussion voices play for a section. */
|
|
49
|
-
export function getPercussionConfig(
|
|
50
|
-
mood: PercMoodCategory,
|
|
51
|
-
section: SectionType,
|
|
52
|
-
): PercussionConfig {
|
|
53
|
-
const row = PERC_TABLE[mood] ?? PERC_TABLE[PercMoodCategory.Standard];
|
|
54
|
-
const act = row?.[sectionIndex(section)] ?? F;
|
|
55
|
-
return {
|
|
56
|
-
tambourine: act[0],
|
|
57
|
-
shaker: act[1],
|
|
58
|
-
handclap: act[2],
|
|
59
|
-
shaker16th: act[1],
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** Emit one bar of auxiliary percussion (tambourine/shaker/handclap). */
|
|
64
|
-
export function generateAuxPercussionForBar(
|
|
65
|
-
track: HitList,
|
|
66
|
-
barStart: number,
|
|
67
|
-
config: PercussionConfig,
|
|
68
|
-
role: DrumRole,
|
|
69
|
-
densityMult: number,
|
|
70
|
-
rng: DrumRng,
|
|
71
|
-
bpm: number,
|
|
72
|
-
): void {
|
|
73
|
-
if (role === 'minimal') {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (config.tambourine) {
|
|
78
|
-
for (let beat = 1; beat <= 3; beat += 2) {
|
|
79
|
-
const raw = 70 * densityMult * rng.float(0.9, 1.1);
|
|
80
|
-
track.add(GM.TAMBOURINE, barStart + beat, EIGHTH, Math.max(40, Math.min(90, raw)));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (config.shaker) {
|
|
85
|
-
const use16th = config.shaker16th && bpm < HH_16TH_BPM_THRESHOLD;
|
|
86
|
-
if (use16th) {
|
|
87
|
-
const velCurve = [0.75, 0.45, 0.6, 0.45];
|
|
88
|
-
for (let beat = 0; beat < 4; beat += 1) {
|
|
89
|
-
for (let sub = 0; sub < 4; sub += 1) {
|
|
90
|
-
const raw = 80 * (velCurve[sub] ?? 0.5) * densityMult * rng.float(0.9, 1.1);
|
|
91
|
-
track.add(
|
|
92
|
-
GM.SHAKER,
|
|
93
|
-
barStart + beat + sub * SIXTEENTH,
|
|
94
|
-
SIXTEENTH,
|
|
95
|
-
Math.max(25, Math.min(85, raw)),
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
const velCurve = [0.75, 0.55];
|
|
101
|
-
for (let beat = 0; beat < 4; beat += 1) {
|
|
102
|
-
for (let sub = 0; sub < 2; sub += 1) {
|
|
103
|
-
const raw = 80 * (velCurve[sub] ?? 0.6) * densityMult * rng.float(0.9, 1.1);
|
|
104
|
-
track.add(
|
|
105
|
-
GM.SHAKER,
|
|
106
|
-
barStart + beat + sub * EIGHTH,
|
|
107
|
-
EIGHTH,
|
|
108
|
-
Math.max(25, Math.min(85, raw)),
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (config.handclap) {
|
|
116
|
-
for (let beat = 1; beat <= 3; beat += 2) {
|
|
117
|
-
const raw = 85 * densityMult * rng.float(0.9, 1.1);
|
|
118
|
-
track.add(GM.HANDCLAP, barStart + beat, EIGHTH, Math.max(50, Math.min(100, raw)));
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The drum engine's PRNG, re-exported from the shared {@link ../random} module.
|
|
3
|
-
* `DrumRng` is retained as the drum-facing name of the shared {@link Rng} type.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export type { Rng as DrumRng } from '../../core/random/index.js';
|
|
7
|
-
export { createRng } from '../../core/random/index.js';
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type { Feel } from './internal.js';
|
|
2
|
-
|
|
3
|
-
const SIXTEENTH = 0.25;
|
|
4
|
-
const EIGHTH = 0.5;
|
|
5
|
-
const HALF_16TH = 0.125;
|
|
6
|
-
/** Delay of an off-beat 16th at full swing (triplet minus straight), in beats. */
|
|
7
|
-
const DELTA_16 = 1 / 3 - 1 / 4; // 0.08333...
|
|
8
|
-
/** Delay of an off-beat 8th at full swing, in beats. */
|
|
9
|
-
const DELTA_8 = (2 / 3 - 1 / 2) / 2 + (2 / 3 - 1 / 2) / 2; // 0.16667...
|
|
10
|
-
|
|
11
|
-
/** Grid resolution for swing quantization. */
|
|
12
|
-
export type SwingResolution = 'eighth' | 'sixteenth';
|
|
13
|
-
|
|
14
|
-
/** Effective swing after applying the groove feel to a base swing amount. */
|
|
15
|
-
export function effectiveSwing(feel: Feel, swingAmount: number): number {
|
|
16
|
-
if (feel === 'straight') {
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
19
|
-
if (feel === 'shuffle') {
|
|
20
|
-
return Math.min(1, swingAmount * 1.5);
|
|
21
|
-
}
|
|
22
|
-
return swingAmount;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Push an off-beat position toward its triplet placement.
|
|
27
|
-
*
|
|
28
|
-
* On-beat positions are returned unchanged; off-beat 8ths and 16ths are delayed
|
|
29
|
-
* proportionally to the swing amount.
|
|
30
|
-
*
|
|
31
|
-
* @param startBeat Absolute position in beats.
|
|
32
|
-
* @param swing Swing amount in [0, 1] (already feel-adjusted).
|
|
33
|
-
* @param resolution Whether to swing the 16th or only the 8th grid.
|
|
34
|
-
* @returns The swung position in beats.
|
|
35
|
-
*/
|
|
36
|
-
export function quantizeSwing(
|
|
37
|
-
startBeat: number,
|
|
38
|
-
swing: number,
|
|
39
|
-
resolution: SwingResolution,
|
|
40
|
-
): number {
|
|
41
|
-
const clamped = Math.max(0, Math.min(1, swing));
|
|
42
|
-
if (clamped <= 0) {
|
|
43
|
-
return startBeat;
|
|
44
|
-
}
|
|
45
|
-
const base = Math.floor(startBeat);
|
|
46
|
-
const offset = startBeat - base;
|
|
47
|
-
|
|
48
|
-
if (resolution === 'sixteenth') {
|
|
49
|
-
if (offset >= HALF_16TH && offset < SIXTEENTH + HALF_16TH) {
|
|
50
|
-
return base + SIXTEENTH + DELTA_16 * clamped;
|
|
51
|
-
}
|
|
52
|
-
if (offset >= SIXTEENTH + HALF_16TH && offset < EIGHTH + HALF_16TH) {
|
|
53
|
-
return base + EIGHTH + DELTA_8 * clamped;
|
|
54
|
-
}
|
|
55
|
-
if (offset >= EIGHTH + HALF_16TH && offset < 3 * SIXTEENTH + HALF_16TH) {
|
|
56
|
-
// The "a" 16th is the midpoint of the compressed second half of the beat
|
|
57
|
-
// (between the swung "and" and the next downbeat), mirroring the "e" 16th
|
|
58
|
-
// in the first half. Because DELTA_8 = 2 * DELTA_16, that midpoint reduces
|
|
59
|
-
// to a single DELTA_16 delay off the straight position, so the "a" never
|
|
60
|
-
// overshoots the downbeat and needs no clamp. At the default shuffle feel
|
|
61
|
-
// (swing 0.75) this lands near 0.8125 rather than the doubly-swung 0.9375.
|
|
62
|
-
return base + 3 * SIXTEENTH + DELTA_16 * clamped;
|
|
63
|
-
}
|
|
64
|
-
return startBeat;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (offset >= SIXTEENTH && offset < 3 * SIXTEENTH) {
|
|
68
|
-
return base + EIGHTH + DELTA_8 * clamped;
|
|
69
|
-
}
|
|
70
|
-
return startBeat;
|
|
71
|
-
}
|