@coldsurf/synth-kit 0.1.0
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/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/bass/index.d.ts +83 -0
- package/dist/bass/index.js +13 -0
- package/dist/bass/index.js.map +1 -0
- package/dist/chunk-CMHDHRZ6.js +61 -0
- package/dist/chunk-CMHDHRZ6.js.map +1 -0
- package/dist/chunk-CNJ6DQV5.js +147 -0
- package/dist/chunk-CNJ6DQV5.js.map +1 -0
- package/dist/drumkit/index.d.ts +153 -0
- package/dist/drumkit/index.js +494 -0
- package/dist/drumkit/index.js.map +1 -0
- package/dist/dub/index.d.ts +103 -0
- package/dist/dub/index.js +183 -0
- package/dist/dub/index.js.map +1 -0
- package/dist/index.d.ts +159 -0
- package/dist/index.js +246 -0
- package/dist/index.js.map +1 -0
- package/dist/space/index.d.ts +56 -0
- package/dist/space/index.js +7 -0
- package/dist/space/index.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
// src/drumkit/drumkit.ts
|
|
2
|
+
function attackTo(param, peak, when, attack, curve) {
|
|
3
|
+
param.setValueAtTime(1e-4, when);
|
|
4
|
+
if (curve === "exp") param.exponentialRampToValueAtTime(peak, when + attack);
|
|
5
|
+
else param.linearRampToValueAtTime(peak, when + attack);
|
|
6
|
+
}
|
|
7
|
+
function createDrumKit(ctx, bus, preset) {
|
|
8
|
+
const noiseBuf = ctx.createBuffer(1, Math.floor(ctx.sampleRate * 1), ctx.sampleRate);
|
|
9
|
+
{
|
|
10
|
+
const d = noiseBuf.getChannelData(0);
|
|
11
|
+
for (let i = 0; i < d.length; i++) d[i] = Math.random() * 2 - 1;
|
|
12
|
+
}
|
|
13
|
+
let stopped = false;
|
|
14
|
+
const pending = /* @__PURE__ */ new Set();
|
|
15
|
+
const trackDispose = (fn, lifetimeMs) => {
|
|
16
|
+
pending.add(fn);
|
|
17
|
+
window.setTimeout(() => {
|
|
18
|
+
if (pending.has(fn)) {
|
|
19
|
+
fn();
|
|
20
|
+
pending.delete(fn);
|
|
21
|
+
}
|
|
22
|
+
}, lifetimeMs);
|
|
23
|
+
};
|
|
24
|
+
function playBody(b, when, velocity) {
|
|
25
|
+
const osc = ctx.createOscillator();
|
|
26
|
+
osc.type = "sine";
|
|
27
|
+
osc.frequency.setValueAtTime(b.startHz, when);
|
|
28
|
+
osc.frequency.exponentialRampToValueAtTime(b.endHz, when + b.pitchTau);
|
|
29
|
+
const g = ctx.createGain();
|
|
30
|
+
attackTo(g.gain, velocity * (b.peakMul ?? 1), when, b.attack, b.attackCurve);
|
|
31
|
+
g.gain.exponentialRampToValueAtTime(1e-4, when + b.decay);
|
|
32
|
+
osc.connect(g).connect(bus);
|
|
33
|
+
osc.start(when);
|
|
34
|
+
osc.stop(when + b.stop);
|
|
35
|
+
trackDispose(
|
|
36
|
+
() => {
|
|
37
|
+
try {
|
|
38
|
+
osc.stop();
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
osc.disconnect();
|
|
42
|
+
g.disconnect();
|
|
43
|
+
},
|
|
44
|
+
(b.stop + 0.1) * 1e3
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function kick(when, velocity) {
|
|
48
|
+
if (stopped) return;
|
|
49
|
+
const k = preset.kick;
|
|
50
|
+
playBody(k.body, when, velocity);
|
|
51
|
+
if (k.sub) playBody(k.sub, when, velocity);
|
|
52
|
+
if (k.click) {
|
|
53
|
+
const c = k.click;
|
|
54
|
+
const src = ctx.createBufferSource();
|
|
55
|
+
src.buffer = noiseBuf;
|
|
56
|
+
const hp = ctx.createBiquadFilter();
|
|
57
|
+
hp.type = "highpass";
|
|
58
|
+
hp.frequency.value = c.hpHz;
|
|
59
|
+
const g = ctx.createGain();
|
|
60
|
+
attackTo(g.gain, velocity * c.level, when, c.attack, c.attackCurve);
|
|
61
|
+
g.gain.exponentialRampToValueAtTime(1e-4, when + c.decay);
|
|
62
|
+
src.connect(hp).connect(g).connect(bus);
|
|
63
|
+
src.start(when);
|
|
64
|
+
src.stop(when + c.stop);
|
|
65
|
+
trackDispose(
|
|
66
|
+
() => {
|
|
67
|
+
try {
|
|
68
|
+
src.stop();
|
|
69
|
+
} catch {
|
|
70
|
+
}
|
|
71
|
+
src.disconnect();
|
|
72
|
+
hp.disconnect();
|
|
73
|
+
g.disconnect();
|
|
74
|
+
},
|
|
75
|
+
(c.stop + 0.1) * 1e3
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function snare(when, velocity) {
|
|
80
|
+
if (stopped || !preset.snare) return;
|
|
81
|
+
const s = preset.snare;
|
|
82
|
+
if (s.tone) {
|
|
83
|
+
const t = s.tone;
|
|
84
|
+
const osc = ctx.createOscillator();
|
|
85
|
+
osc.type = t.type;
|
|
86
|
+
osc.frequency.setValueAtTime(t.startHz, when);
|
|
87
|
+
if (t.endHz !== void 0) {
|
|
88
|
+
osc.frequency.exponentialRampToValueAtTime(t.endHz, when + (t.pitchTau ?? 0.08));
|
|
89
|
+
}
|
|
90
|
+
const g = ctx.createGain();
|
|
91
|
+
attackTo(g.gain, velocity * t.level, when, 3e-3, "lin");
|
|
92
|
+
g.gain.exponentialRampToValueAtTime(1e-4, when + t.decay);
|
|
93
|
+
osc.connect(g).connect(bus);
|
|
94
|
+
osc.start(when);
|
|
95
|
+
osc.stop(when + t.stop);
|
|
96
|
+
trackDispose(
|
|
97
|
+
() => {
|
|
98
|
+
try {
|
|
99
|
+
osc.stop();
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
osc.disconnect();
|
|
103
|
+
g.disconnect();
|
|
104
|
+
},
|
|
105
|
+
(t.stop + 0.1) * 1e3
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if (s.noise) {
|
|
109
|
+
const n = s.noise;
|
|
110
|
+
const src = ctx.createBufferSource();
|
|
111
|
+
src.buffer = noiseBuf;
|
|
112
|
+
src.playbackRate.value = n.prMin + Math.random() * (n.prMax - n.prMin);
|
|
113
|
+
const bp = ctx.createBiquadFilter();
|
|
114
|
+
bp.type = "bandpass";
|
|
115
|
+
bp.frequency.value = n.bpHz;
|
|
116
|
+
bp.Q.value = n.q;
|
|
117
|
+
const g = ctx.createGain();
|
|
118
|
+
attackTo(g.gain, velocity * n.level, when, 2e-3, "lin");
|
|
119
|
+
g.gain.exponentialRampToValueAtTime(1e-4, when + n.decay);
|
|
120
|
+
src.connect(bp).connect(g).connect(bus);
|
|
121
|
+
src.start(when);
|
|
122
|
+
src.stop(when + n.stop);
|
|
123
|
+
trackDispose(
|
|
124
|
+
() => {
|
|
125
|
+
try {
|
|
126
|
+
src.stop();
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
src.disconnect();
|
|
130
|
+
bp.disconnect();
|
|
131
|
+
g.disconnect();
|
|
132
|
+
},
|
|
133
|
+
(n.stop + 0.1) * 1e3
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
if (s.gatedTails) {
|
|
137
|
+
for (const tl of s.gatedTails) {
|
|
138
|
+
const src = ctx.createBufferSource();
|
|
139
|
+
src.buffer = noiseBuf;
|
|
140
|
+
src.playbackRate.value = 0.7 + Math.random() * 0.2;
|
|
141
|
+
const bp = ctx.createBiquadFilter();
|
|
142
|
+
bp.type = "bandpass";
|
|
143
|
+
bp.frequency.value = tl.centerHz;
|
|
144
|
+
bp.Q.value = tl.q;
|
|
145
|
+
const g = ctx.createGain();
|
|
146
|
+
const peak = velocity * tl.level;
|
|
147
|
+
g.gain.setValueAtTime(1e-4, when);
|
|
148
|
+
g.gain.linearRampToValueAtTime(peak, when + 6e-3);
|
|
149
|
+
g.gain.setValueAtTime(peak * 0.85, when + tl.plateau);
|
|
150
|
+
g.gain.linearRampToValueAtTime(1e-4, when + tl.plateau + tl.cut);
|
|
151
|
+
src.connect(bp).connect(g).connect(bus);
|
|
152
|
+
src.start(when);
|
|
153
|
+
const stop = tl.plateau + tl.cut + 0.05;
|
|
154
|
+
src.stop(when + stop);
|
|
155
|
+
trackDispose(
|
|
156
|
+
() => {
|
|
157
|
+
try {
|
|
158
|
+
src.stop();
|
|
159
|
+
} catch {
|
|
160
|
+
}
|
|
161
|
+
src.disconnect();
|
|
162
|
+
bp.disconnect();
|
|
163
|
+
g.disconnect();
|
|
164
|
+
},
|
|
165
|
+
(stop + 0.1) * 1e3
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function hat(when, velocity, open) {
|
|
171
|
+
if (stopped || !preset.hat) return;
|
|
172
|
+
const h = preset.hat;
|
|
173
|
+
const src = ctx.createBufferSource();
|
|
174
|
+
src.buffer = noiseBuf;
|
|
175
|
+
src.playbackRate.value = h.prCenter + (Math.random() - 0.5) * h.prSpread;
|
|
176
|
+
const hp = ctx.createBiquadFilter();
|
|
177
|
+
hp.type = "highpass";
|
|
178
|
+
hp.frequency.value = h.hpHz;
|
|
179
|
+
if (h.hpQ !== void 0) hp.Q.value = h.hpQ;
|
|
180
|
+
let tail = hp;
|
|
181
|
+
let bp = null;
|
|
182
|
+
if (h.bpHz !== void 0) {
|
|
183
|
+
bp = ctx.createBiquadFilter();
|
|
184
|
+
bp.type = "bandpass";
|
|
185
|
+
bp.frequency.value = h.bpHz;
|
|
186
|
+
if (h.bpQ !== void 0) bp.Q.value = h.bpQ;
|
|
187
|
+
hp.connect(bp);
|
|
188
|
+
tail = bp;
|
|
189
|
+
}
|
|
190
|
+
const decay = open ? h.openDecay : h.closedDecay;
|
|
191
|
+
const peak = velocity * (open ? h.openLevel : h.closedLevel);
|
|
192
|
+
const g = ctx.createGain();
|
|
193
|
+
attackTo(g.gain, peak, when, h.attack, "lin");
|
|
194
|
+
g.gain.exponentialRampToValueAtTime(1e-4, when + decay);
|
|
195
|
+
src.connect(hp);
|
|
196
|
+
tail.connect(g).connect(bus);
|
|
197
|
+
src.start(when);
|
|
198
|
+
const stop = decay + h.stopPad;
|
|
199
|
+
src.stop(when + stop);
|
|
200
|
+
trackDispose(
|
|
201
|
+
() => {
|
|
202
|
+
try {
|
|
203
|
+
src.stop();
|
|
204
|
+
} catch {
|
|
205
|
+
}
|
|
206
|
+
src.disconnect();
|
|
207
|
+
hp.disconnect();
|
|
208
|
+
bp?.disconnect();
|
|
209
|
+
g.disconnect();
|
|
210
|
+
},
|
|
211
|
+
(stop + 0.1) * 1e3
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
kick,
|
|
216
|
+
snare,
|
|
217
|
+
hat,
|
|
218
|
+
dispose() {
|
|
219
|
+
stopped = true;
|
|
220
|
+
for (const fn of pending) {
|
|
221
|
+
try {
|
|
222
|
+
fn();
|
|
223
|
+
} catch {
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
pending.clear();
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// src/drumkit/kits.ts
|
|
232
|
+
var DRY_KIT = {
|
|
233
|
+
kick: {
|
|
234
|
+
body: {
|
|
235
|
+
startHz: 135,
|
|
236
|
+
endHz: 48,
|
|
237
|
+
pitchTau: 0.06,
|
|
238
|
+
attack: 4e-3,
|
|
239
|
+
attackCurve: "lin",
|
|
240
|
+
decay: 0.32,
|
|
241
|
+
stop: 0.4
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
snare: {
|
|
245
|
+
tone: { type: "triangle", startHz: 220, level: 0.45, decay: 0.14, stop: 0.18 },
|
|
246
|
+
noise: { bpHz: 1600, q: 0.8, prMin: 0.6, prMax: 1, level: 0.5, decay: 0.18, stop: 0.22 }
|
|
247
|
+
},
|
|
248
|
+
hat: {
|
|
249
|
+
hpHz: 7200,
|
|
250
|
+
hpQ: 0.6,
|
|
251
|
+
prCenter: 1,
|
|
252
|
+
prSpread: 0.1,
|
|
253
|
+
attack: 2e-3,
|
|
254
|
+
closedDecay: 0.04,
|
|
255
|
+
openDecay: 0.22,
|
|
256
|
+
closedLevel: 1,
|
|
257
|
+
openLevel: 1,
|
|
258
|
+
stopPad: 0.05
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
var WET_KIT = {
|
|
262
|
+
kick: {
|
|
263
|
+
body: {
|
|
264
|
+
startHz: 110,
|
|
265
|
+
endHz: 42,
|
|
266
|
+
pitchTau: 0.09,
|
|
267
|
+
attack: 6e-3,
|
|
268
|
+
attackCurve: "lin",
|
|
269
|
+
decay: 0.5,
|
|
270
|
+
stop: 0.55
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
snare: {
|
|
274
|
+
tone: { type: "triangle", startHz: 200, level: 0.5, decay: 0.12, stop: 0.18 },
|
|
275
|
+
noise: { bpHz: 1800, q: 0.9, prMin: 1, prMax: 1, level: 0.6, decay: 0.14, stop: 0.18 },
|
|
276
|
+
gatedTails: [
|
|
277
|
+
{ centerHz: 1400, q: 1.2, level: 0.55, plateau: 0.18, cut: 0.02 },
|
|
278
|
+
{ centerHz: 450, q: 1, level: 0.4, plateau: 0.18, cut: 0.02 }
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
var IRON_KIT = {
|
|
283
|
+
kick: {
|
|
284
|
+
body: {
|
|
285
|
+
startHz: 95,
|
|
286
|
+
endHz: 38,
|
|
287
|
+
pitchTau: 0.05,
|
|
288
|
+
attack: 3e-3,
|
|
289
|
+
attackCurve: "lin",
|
|
290
|
+
decay: 0.28,
|
|
291
|
+
stop: 0.35
|
|
292
|
+
},
|
|
293
|
+
click: { hpHz: 2200, level: 0.35, attack: 1e-3, attackCurve: "lin", decay: 0.012, stop: 0.03 }
|
|
294
|
+
},
|
|
295
|
+
// grit = ๊ฑฐ์น highpass noise. open ๋ชจ๋ ์์ด closed ๋ง ํธ์ถ โ openDecay = closedDecay.
|
|
296
|
+
hat: {
|
|
297
|
+
hpHz: 6500,
|
|
298
|
+
hpQ: 0.5,
|
|
299
|
+
prCenter: 1,
|
|
300
|
+
prSpread: 0.3,
|
|
301
|
+
attack: 1e-3,
|
|
302
|
+
closedDecay: 0.035,
|
|
303
|
+
openDecay: 0.035,
|
|
304
|
+
closedLevel: 1,
|
|
305
|
+
openLevel: 1,
|
|
306
|
+
stopPad: 0.045
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
var BLACKGAZE_SNARE = {
|
|
310
|
+
noise: { bpHz: 1800, q: 1.3, prMin: 1, prMax: 1, level: 0.6, decay: 0.2, stop: 0.25 },
|
|
311
|
+
tone: {
|
|
312
|
+
type: "triangle",
|
|
313
|
+
startHz: 260,
|
|
314
|
+
endHz: 160,
|
|
315
|
+
pitchTau: 0.08,
|
|
316
|
+
level: 0.32,
|
|
317
|
+
decay: 0.13,
|
|
318
|
+
stop: 0.18
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
var BATHEDAY_KIT = {
|
|
322
|
+
kick: {
|
|
323
|
+
body: {
|
|
324
|
+
startHz: 150,
|
|
325
|
+
endHz: 45,
|
|
326
|
+
pitchTau: 0.07,
|
|
327
|
+
attack: 4e-3,
|
|
328
|
+
attackCurve: "lin",
|
|
329
|
+
decay: 0.34,
|
|
330
|
+
stop: 0.4
|
|
331
|
+
},
|
|
332
|
+
click: { hpHz: 2200, level: 0.28, attack: 1e-3, attackCurve: "lin", decay: 0.01, stop: 0.03 }
|
|
333
|
+
},
|
|
334
|
+
snare: BLACKGAZE_SNARE
|
|
335
|
+
};
|
|
336
|
+
var SUBLIME_KIT = BATHEDAY_KIT;
|
|
337
|
+
var REVEAL_KIT = {
|
|
338
|
+
kick: {
|
|
339
|
+
body: {
|
|
340
|
+
startHz: 140,
|
|
341
|
+
endHz: 42,
|
|
342
|
+
pitchTau: 0.07,
|
|
343
|
+
attack: 4e-3,
|
|
344
|
+
attackCurve: "lin",
|
|
345
|
+
decay: 0.38,
|
|
346
|
+
stop: 0.45
|
|
347
|
+
},
|
|
348
|
+
click: { hpHz: 1800, level: 0.25, attack: 1e-3, attackCurve: "lin", decay: 0.01, stop: 0.03 }
|
|
349
|
+
},
|
|
350
|
+
snare: {
|
|
351
|
+
noise: { bpHz: 1700, q: 1.4, prMin: 1, prMax: 1, level: 0.55, decay: 0.18, stop: 0.25 },
|
|
352
|
+
tone: {
|
|
353
|
+
type: "triangle",
|
|
354
|
+
startHz: 240,
|
|
355
|
+
endHz: 150,
|
|
356
|
+
pitchTau: 0.08,
|
|
357
|
+
level: 0.3,
|
|
358
|
+
decay: 0.12,
|
|
359
|
+
stop: 0.18
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
hat: {
|
|
363
|
+
hpHz: 7200,
|
|
364
|
+
prCenter: 1,
|
|
365
|
+
prSpread: 0.3,
|
|
366
|
+
attack: 1e-3,
|
|
367
|
+
closedDecay: 0.025,
|
|
368
|
+
openDecay: 0.12,
|
|
369
|
+
closedLevel: 1,
|
|
370
|
+
openLevel: 1,
|
|
371
|
+
stopPad: 0.02
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
var DUB_RELAY_KIT = {
|
|
375
|
+
kick: {
|
|
376
|
+
body: {
|
|
377
|
+
startHz: 130,
|
|
378
|
+
endHz: 48,
|
|
379
|
+
pitchTau: 0.08,
|
|
380
|
+
attack: 4e-3,
|
|
381
|
+
attackCurve: "exp",
|
|
382
|
+
peakMul: 1.3,
|
|
383
|
+
decay: 0.6,
|
|
384
|
+
stop: 0.65
|
|
385
|
+
},
|
|
386
|
+
sub: {
|
|
387
|
+
startHz: 60,
|
|
388
|
+
endHz: 38,
|
|
389
|
+
pitchTau: 0.12,
|
|
390
|
+
attack: 8e-3,
|
|
391
|
+
attackCurve: "exp",
|
|
392
|
+
peakMul: 0.95,
|
|
393
|
+
decay: 0.45,
|
|
394
|
+
stop: 0.5
|
|
395
|
+
},
|
|
396
|
+
click: { hpHz: 2500, level: 0.4, attack: 1e-3, attackCurve: "exp", decay: 0.02, stop: 0.04 }
|
|
397
|
+
},
|
|
398
|
+
hat: {
|
|
399
|
+
hpHz: 7800,
|
|
400
|
+
bpHz: 9e3,
|
|
401
|
+
bpQ: 0.9,
|
|
402
|
+
prCenter: 1,
|
|
403
|
+
prSpread: 0.05,
|
|
404
|
+
attack: 2e-3,
|
|
405
|
+
closedDecay: 0.035,
|
|
406
|
+
openDecay: 0.13,
|
|
407
|
+
closedLevel: 0.22,
|
|
408
|
+
openLevel: 0.32,
|
|
409
|
+
stopPad: 0.02
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
var DUB_HOLY_KIT = {
|
|
413
|
+
kick: {
|
|
414
|
+
body: {
|
|
415
|
+
startHz: 140,
|
|
416
|
+
endHz: 44,
|
|
417
|
+
pitchTau: 0.1,
|
|
418
|
+
attack: 5e-3,
|
|
419
|
+
attackCurve: "exp",
|
|
420
|
+
peakMul: 1.4,
|
|
421
|
+
decay: 0.85,
|
|
422
|
+
stop: 0.9
|
|
423
|
+
},
|
|
424
|
+
sub: {
|
|
425
|
+
startHz: 56,
|
|
426
|
+
endHz: 36,
|
|
427
|
+
pitchTau: 0.15,
|
|
428
|
+
attack: 0.01,
|
|
429
|
+
attackCurve: "exp",
|
|
430
|
+
peakMul: 1.05,
|
|
431
|
+
decay: 0.7,
|
|
432
|
+
stop: 0.75
|
|
433
|
+
},
|
|
434
|
+
click: {
|
|
435
|
+
hpHz: 2200,
|
|
436
|
+
level: 0.32,
|
|
437
|
+
attack: 15e-4,
|
|
438
|
+
attackCurve: "exp",
|
|
439
|
+
decay: 0.025,
|
|
440
|
+
stop: 0.05
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
var DUB_POWER_KIT = {
|
|
445
|
+
kick: {
|
|
446
|
+
body: {
|
|
447
|
+
startHz: 140,
|
|
448
|
+
endHz: 45,
|
|
449
|
+
pitchTau: 0.1,
|
|
450
|
+
attack: 5e-3,
|
|
451
|
+
attackCurve: "exp",
|
|
452
|
+
peakMul: 1.35,
|
|
453
|
+
decay: 0.75,
|
|
454
|
+
stop: 0.8
|
|
455
|
+
},
|
|
456
|
+
sub: {
|
|
457
|
+
startHz: 64.6,
|
|
458
|
+
endHz: 38,
|
|
459
|
+
pitchTau: 0.15,
|
|
460
|
+
attack: 0.01,
|
|
461
|
+
attackCurve: "exp",
|
|
462
|
+
peakMul: 1.05,
|
|
463
|
+
decay: 0.6,
|
|
464
|
+
stop: 0.65
|
|
465
|
+
},
|
|
466
|
+
click: { hpHz: 2200, level: 0.32, attack: 1e-3, attackCurve: "exp", decay: 0.025, stop: 0.04 }
|
|
467
|
+
},
|
|
468
|
+
hat: {
|
|
469
|
+
hpHz: 6500,
|
|
470
|
+
bpHz: 7200,
|
|
471
|
+
bpQ: 0.85,
|
|
472
|
+
prCenter: 1,
|
|
473
|
+
prSpread: 0.06,
|
|
474
|
+
attack: 2e-3,
|
|
475
|
+
closedDecay: 0.045,
|
|
476
|
+
openDecay: 0.22,
|
|
477
|
+
closedLevel: 0.24,
|
|
478
|
+
openLevel: 0.34,
|
|
479
|
+
stopPad: 0.02
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
export {
|
|
483
|
+
BATHEDAY_KIT,
|
|
484
|
+
DRY_KIT,
|
|
485
|
+
DUB_HOLY_KIT,
|
|
486
|
+
DUB_POWER_KIT,
|
|
487
|
+
DUB_RELAY_KIT,
|
|
488
|
+
IRON_KIT,
|
|
489
|
+
REVEAL_KIT,
|
|
490
|
+
SUBLIME_KIT,
|
|
491
|
+
WET_KIT,
|
|
492
|
+
createDrumKit
|
|
493
|
+
};
|
|
494
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/drumkit/drumkit.ts","../../src/drumkit/kits.ts"],"sourcesContent":["/**\n * Drumkit โ *ํ์
* ํฉ์ฑ ์์ง. catalog ํธ๋๋ค์ด ๊ธ์ ๊ทธ๋๋ก ๋ณต์ ํ๋ kickยทsnareยทhat ๊ณจ๊ฒฉ์\n * ํ ์
๊ธฐ๋ก. sunwall ๊ณผ ๊ฐ์ VST ๋ชจ๋ธ: `createDrumKit` ์ *์-๋ถ๋ฌธ ์์ง*, `*_KIT` ์ *ํจ์น*.\n *\n * kick : body osc(ํผ์น envelope) โ gain env โ bus (+ ์ต์
sub body, click transient)\n * snare : tone osc + bandpass noise (+ ์ต์
gated reverb tail ร N)\n * hat : highpass(+์ต์
bandpass) noise โ gain env (closed/open)\n *\n * ์์ง์ *voice ํฉ์ฑ* ๋ง ํ๋ค โ `(when, velocity)` ์ ๋์๊ฐ์ผ๋ก `bus` ์ ํ ํ๊ฒฉ์ ๊ทธ๋ฆฐ๋ค.\n * ์ค์ผ์ค๋ง(์คํ
๋ฃจํ)ยทmaster fadeยท์ฌ์ด๋์ฒด์ธ duckยทdub send ๋ *ํธ๋* ์ ์ฑ
์์ด๋ฉฐ ์์ง ๋ฐ์ด๋ค.\n * ํ ๊ณก ์ ์ฉ voice(metalHitยทtomยทshimmerยทsaluteยท\n * crashยทclapยทrim)๋ rule-of-three ๋ฏธ๋ฌ์ด๋ผ ํธ๋ ์ธ๋ผ์ธ์ผ๋ก ๋จ๋๋ค.\n *\n * ๋ณด์กด ๊ธฐ์ค: ๋ค๋ฆฌ๋ envelope(attackยทpeakยทdecay)ยทํํฐยทํผ์น๋ ์๋ณธ ์์ ๊ทธ๋๋ก. ๋ค๋ฆฌ์ง ์๋\n * ๊ฒ๋ง ์ ๊ทํ โ โ white noise ๋ฒํผ ๋ด์ฉ(ํต๊ณ์ ์ผ๋ก ๋์ผํ ๋์), โก ์ผ๋ถ ๋
ธ๋ stop() ์์ ์\n * preset ์ `stop`/`stopPad` ๋ก ๊ทธ๋๋ก ๋ฐ๋๋ค.\n */\n\n/** envelope ramp ์ข
๋ฅ. dub kick ์ exp attack(peak>velocity ํ์ฉ), ๊ทธ ์ธ์ lin. */\ntype Ramp = 'lin' | 'exp'\n\n/** ํผ์น + gain envelope ํ layer (kick bodyยทsub ๊ณต์ฉ). */\nexport interface KickBody {\n startHz: number\n endHz: number\n /** freq exponentialRamp ๋๋ฌ ์๊ฐ. */\n pitchTau: number\n /** gain attack ์๊ฐ. */\n attack: number\n attackCurve: Ramp\n /** peak gain = velocity * peakMul. ๊ธฐ๋ณธ 1. dub body1 ์ 1.3 ๋ฑ. */\n peakMul?: number\n /** gain exponentialRampโ0 ๋๋ฌ ์๊ฐ(=๊ฐ์ ๋). */\n decay: number\n /** osc.stop(when + stop). */\n stop: number\n}\n\n/** kick transient click โ ์งง์ highpass noise burst. */\nexport interface KickClick {\n hpHz: number\n /** peak = velocity * level. */\n level: number\n attack: number\n attackCurve: Ramp\n decay: number\n stop: number\n}\n\nexport interface KickPreset {\n body: KickBody\n /** dub ์ ์ฉ โ ๊น์ sub tail layer. */\n sub?: KickBody\n click?: KickClick\n}\n\nexport interface SnareTone {\n type: OscillatorType\n startHz: number\n /** ์์ผ๋ฉด startHz โ endHz ํผ์น envelope. */\n endHz?: number\n pitchTau?: number\n /** peak = velocity * level. */\n level: number\n decay: number\n stop: number\n}\n\nexport interface SnareNoise {\n bpHz: number\n q: number\n /** playbackRate โ [prMin, prMax] ๋ฌด์์. ๊ณ ์ ์ด๋ฉด ๋ ๊ฐ ๋์ผ. */\n prMin: number\n prMax: number\n level: number\n decay: number\n stop: number\n}\n\n/** Gated reverb tail (wet-room ์ *In the Air Tonight* ๊ฒฐ). ์์ฐ ๊ฐ์ ๋์ plateau โ cut. */\nexport interface GatedTail {\n centerHz: number\n q: number\n /** peak = velocity * level. */\n level: number\n plateau: number\n cut: number\n}\n\nexport interface SnarePreset {\n tone?: SnareTone\n noise?: SnareNoise\n gatedTails?: GatedTail[]\n}\n\nexport interface HatPreset {\n hpHz: number\n hpQ?: number\n /** ์์ผ๋ฉด highpass ๋ค์ bandpass ํ ๋จ(dub hat). */\n bpHz?: number\n bpQ?: number\n /** playbackRate = prCenter + (random - 0.5) * prSpread. */\n prCenter: number\n prSpread: number\n attack: number\n closedDecay: number\n openDecay: number\n /** peak = velocity * (open ? openLevel : closedLevel). dry/iron/reveal ์ 1. */\n closedLevel: number\n openLevel: number\n /** stop = when + tail + stopPad. */\n stopPad: number\n}\n\nexport interface DrumKitPreset {\n kick: KickPreset\n snare?: SnarePreset\n hat?: HatPreset\n}\n\nexport interface DrumKitHandle {\n /** when ์ kick ํ ํ. */\n kick(when: number, velocity: number): void\n /** when ์ snare ํ ํ. preset.snare ์์ผ๋ฉด no-op. */\n snare(when: number, velocity: number): void\n /** when ์ hat ํ ํ(open/closed). preset.hat ์์ผ๋ฉด no-op. */\n hat(when: number, velocity: number, open: boolean): void\n /** ๊ณต์ ๋
ธ๋ ์ ๋ฆฌ. ephemeral voice ๋
ธ๋๋ self-stop + ๋ด๋ถ ํ์์์ disconnect. */\n dispose(): void\n}\n\n/** attack ramp ํ ์ค โ 0.0001 ์์ peak ๊น์ง lin/exp. */\nfunction attackTo(param: AudioParam, peak: number, when: number, attack: number, curve: Ramp) {\n param.setValueAtTime(0.0001, when)\n if (curve === 'exp') param.exponentialRampToValueAtTime(peak, when + attack)\n else param.linearRampToValueAtTime(peak, when + attack)\n}\n\n/**\n * ๋๋ผํท์ ๋ง๋ค์ด `bus` ๋ก voice ๋ฅผ ํฉ์ฑํ๋ ํธ๋ค์ ๋๋ ค์ค๋ค.\n *\n * @param bus ๊ฐ ํ๊ฒฉ์ด ์ฐ๊ฒฐ๋ ๋ชฉ์ ์ง(ํธ๋์ drumBusยทtoneยทmaster ๋ฑ).\n */\nexport function createDrumKit(\n ctx: AudioContext,\n bus: AudioNode,\n preset: DrumKitPreset,\n): DrumKitHandle {\n // ๊ณต์ white noise ๋ฒํผ โ snareยทhat ์ ์ฌ๋ฃ. 1s ๋ฉด ๋ชจ๋ kit voice tail ์ ๋ฎ๋๋ค.\n // ๋ด์ฉ์ ๋์๋ผ ํธ๋๋ณ ์๋ณธ๊ณผ *ํต๊ณ์ ์ผ๋ก ๋์ผ*(perceptually identical).\n const noiseBuf = ctx.createBuffer(1, Math.floor(ctx.sampleRate * 1.0), ctx.sampleRate)\n {\n const d = noiseBuf.getChannelData(0)\n for (let i = 0; i < d.length; i++) d[i] = Math.random() * 2 - 1\n }\n\n // ephemeral voice ๋
ธ๋์ ์ง์ฐ disconnect โ ๊ธฐ์กด trackDispose ๋์์ ์์ง ๋ด๋ถ๋ก ํก์.\n let stopped = false\n const pending = new Set<() => void>()\n const trackDispose = (fn: () => void, lifetimeMs: number) => {\n pending.add(fn)\n window.setTimeout(() => {\n if (pending.has(fn)) {\n fn()\n pending.delete(fn)\n }\n }, lifetimeMs)\n }\n\n function playBody(b: KickBody, when: number, velocity: number) {\n const osc = ctx.createOscillator()\n osc.type = 'sine'\n osc.frequency.setValueAtTime(b.startHz, when)\n osc.frequency.exponentialRampToValueAtTime(b.endHz, when + b.pitchTau)\n const g = ctx.createGain()\n attackTo(g.gain, velocity * (b.peakMul ?? 1), when, b.attack, b.attackCurve)\n g.gain.exponentialRampToValueAtTime(0.0001, when + b.decay)\n osc.connect(g).connect(bus)\n osc.start(when)\n osc.stop(when + b.stop)\n trackDispose(\n () => {\n try {\n osc.stop()\n } catch {\n // ์ด๋ฏธ ์ ์ง โ ๋ฌดํด.\n }\n osc.disconnect()\n g.disconnect()\n },\n (b.stop + 0.1) * 1000,\n )\n }\n\n function kick(when: number, velocity: number) {\n if (stopped) return\n const k = preset.kick\n playBody(k.body, when, velocity)\n if (k.sub) playBody(k.sub, when, velocity)\n if (k.click) {\n const c = k.click\n const src = ctx.createBufferSource()\n src.buffer = noiseBuf\n const hp = ctx.createBiquadFilter()\n hp.type = 'highpass'\n hp.frequency.value = c.hpHz\n const g = ctx.createGain()\n attackTo(g.gain, velocity * c.level, when, c.attack, c.attackCurve)\n g.gain.exponentialRampToValueAtTime(0.0001, when + c.decay)\n src.connect(hp).connect(g).connect(bus)\n src.start(when)\n src.stop(when + c.stop)\n trackDispose(\n () => {\n try {\n src.stop()\n } catch {\n // ์ด๋ฏธ ์ ์ง โ ๋ฌดํด.\n }\n src.disconnect()\n hp.disconnect()\n g.disconnect()\n },\n (c.stop + 0.1) * 1000,\n )\n }\n }\n\n function snare(when: number, velocity: number) {\n if (stopped || !preset.snare) return\n const s = preset.snare\n\n if (s.tone) {\n const t = s.tone\n const osc = ctx.createOscillator()\n osc.type = t.type\n osc.frequency.setValueAtTime(t.startHz, when)\n if (t.endHz !== undefined) {\n osc.frequency.exponentialRampToValueAtTime(t.endHz, when + (t.pitchTau ?? 0.08))\n }\n const g = ctx.createGain()\n attackTo(g.gain, velocity * t.level, when, 0.003, 'lin')\n g.gain.exponentialRampToValueAtTime(0.0001, when + t.decay)\n osc.connect(g).connect(bus)\n osc.start(when)\n osc.stop(when + t.stop)\n trackDispose(\n () => {\n try {\n osc.stop()\n } catch {\n // ์ด๋ฏธ ์ ์ง โ ๋ฌดํด.\n }\n osc.disconnect()\n g.disconnect()\n },\n (t.stop + 0.1) * 1000,\n )\n }\n\n if (s.noise) {\n const n = s.noise\n const src = ctx.createBufferSource()\n src.buffer = noiseBuf\n src.playbackRate.value = n.prMin + Math.random() * (n.prMax - n.prMin)\n const bp = ctx.createBiquadFilter()\n bp.type = 'bandpass'\n bp.frequency.value = n.bpHz\n bp.Q.value = n.q\n const g = ctx.createGain()\n attackTo(g.gain, velocity * n.level, when, 0.002, 'lin')\n g.gain.exponentialRampToValueAtTime(0.0001, when + n.decay)\n src.connect(bp).connect(g).connect(bus)\n src.start(when)\n src.stop(when + n.stop)\n trackDispose(\n () => {\n try {\n src.stop()\n } catch {\n // ์ด๋ฏธ ์ ์ง โ ๋ฌดํด.\n }\n src.disconnect()\n bp.disconnect()\n g.disconnect()\n },\n (n.stop + 0.1) * 1000,\n )\n }\n\n if (s.gatedTails) {\n for (const tl of s.gatedTails) {\n const src = ctx.createBufferSource()\n src.buffer = noiseBuf\n src.playbackRate.value = 0.7 + Math.random() * 0.2\n const bp = ctx.createBiquadFilter()\n bp.type = 'bandpass'\n bp.frequency.value = tl.centerHz\n bp.Q.value = tl.q\n const g = ctx.createGain()\n const peak = velocity * tl.level\n // attack โ plateau โ ๊ฐ์๊ธฐ cut (์์ฐ ๊ฐ์ ๊ฐ ์๋ *gated*).\n g.gain.setValueAtTime(0.0001, when)\n g.gain.linearRampToValueAtTime(peak, when + 0.006)\n g.gain.setValueAtTime(peak * 0.85, when + tl.plateau)\n g.gain.linearRampToValueAtTime(0.0001, when + tl.plateau + tl.cut)\n src.connect(bp).connect(g).connect(bus)\n src.start(when)\n const stop = tl.plateau + tl.cut + 0.05\n src.stop(when + stop)\n trackDispose(\n () => {\n try {\n src.stop()\n } catch {\n // ์ด๋ฏธ ์ ์ง โ ๋ฌดํด.\n }\n src.disconnect()\n bp.disconnect()\n g.disconnect()\n },\n (stop + 0.1) * 1000,\n )\n }\n }\n }\n\n function hat(when: number, velocity: number, open: boolean) {\n if (stopped || !preset.hat) return\n const h = preset.hat\n const src = ctx.createBufferSource()\n src.buffer = noiseBuf\n src.playbackRate.value = h.prCenter + (Math.random() - 0.5) * h.prSpread\n const hp = ctx.createBiquadFilter()\n hp.type = 'highpass'\n hp.frequency.value = h.hpHz\n if (h.hpQ !== undefined) hp.Q.value = h.hpQ\n\n let tail: AudioNode = hp\n let bp: BiquadFilterNode | null = null\n if (h.bpHz !== undefined) {\n bp = ctx.createBiquadFilter()\n bp.type = 'bandpass'\n bp.frequency.value = h.bpHz\n if (h.bpQ !== undefined) bp.Q.value = h.bpQ\n hp.connect(bp)\n tail = bp\n }\n\n const decay = open ? h.openDecay : h.closedDecay\n const peak = velocity * (open ? h.openLevel : h.closedLevel)\n const g = ctx.createGain()\n attackTo(g.gain, peak, when, h.attack, 'lin')\n g.gain.exponentialRampToValueAtTime(0.0001, when + decay)\n src.connect(hp)\n tail.connect(g).connect(bus)\n src.start(when)\n const stop = decay + h.stopPad\n src.stop(when + stop)\n trackDispose(\n () => {\n try {\n src.stop()\n } catch {\n // ์ด๋ฏธ ์ ์ง โ ๋ฌดํด.\n }\n src.disconnect()\n hp.disconnect()\n bp?.disconnect()\n g.disconnect()\n },\n (stop + 0.1) * 1000,\n )\n }\n\n return {\n kick,\n snare,\n hat,\n dispose() {\n stopped = true\n for (const fn of pending) {\n try {\n fn()\n } catch {\n // ์ด๋ฏธ ์ ๋ฆฌ๋จ โ ๋ฌดํด.\n }\n }\n pending.clear()\n },\n }\n}\n","/**\n * Drumkit presets โ *kit ํจ์น*. ํธ๋๋น ํ๋. ๊ฐ ํธ๋ ์ธ๋ผ์ธ ๋๋ผ์ *๋ค๋ฆฌ๋ ์์* ๋ฅผ ๊ทธ๋๋ก\n * ์ฎ๊ธด ๊ฒ์ด๋ผ, ๊ฑฐ์ ๊ฐ์ ๋ณด์ฌ๋(์: batheday 150โ45 vs gratis 140โ42) ํฉ์น์ง ์๋๋ค โ\n * *์๋ฆฌ ๋ณด์กด* ์ด ๊ธฐ์ค. dedup ์ด๋์ ์์ง(`createDrumKit`)์ด์ง\n * preset ์๊ฐ ์๋๋ค.\n */\n\nimport type { DrumKitPreset, SnarePreset } from './drumkit'\n\n// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n// Dry / Wet / Iron โ *๋จธ์ ์ดํ* 3 ๋ณ์ฃผ.\n// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n\n/** dry-room โ LinnDrum/DR-55 ์ dry punch. tail ์๋ ๋ง๋ฅธ ๋จธ์ . */\nexport const DRY_KIT: DrumKitPreset = {\n kick: {\n body: {\n startHz: 135,\n endHz: 48,\n pitchTau: 0.06,\n attack: 0.004,\n attackCurve: 'lin',\n decay: 0.32,\n stop: 0.4,\n },\n },\n snare: {\n tone: { type: 'triangle', startHz: 220, level: 0.45, decay: 0.14, stop: 0.18 },\n noise: { bpHz: 1600, q: 0.8, prMin: 0.6, prMax: 1.0, level: 0.5, decay: 0.18, stop: 0.22 },\n },\n hat: {\n hpHz: 7200,\n hpQ: 0.6,\n prCenter: 1.0,\n prSpread: 0.1,\n attack: 0.002,\n closedDecay: 0.04,\n openDecay: 0.22,\n closedLevel: 1,\n openLevel: 1,\n stopPad: 0.05,\n },\n}\n\n/** wet-room โ ๊น๊ณ ๊ธด sine kick + *gated reverb* snare(In the Air Tonight). */\nexport const WET_KIT: DrumKitPreset = {\n kick: {\n body: {\n startHz: 110,\n endHz: 42,\n pitchTau: 0.09,\n attack: 0.006,\n attackCurve: 'lin',\n decay: 0.5,\n stop: 0.55,\n },\n },\n snare: {\n tone: { type: 'triangle', startHz: 200, level: 0.5, decay: 0.12, stop: 0.18 },\n noise: { bpHz: 1800, q: 0.9, prMin: 1.0, prMax: 1.0, level: 0.6, decay: 0.14, stop: 0.18 },\n gatedTails: [\n { centerHz: 1400, q: 1.2, level: 0.55, plateau: 0.18, cut: 0.02 },\n { centerHz: 450, q: 1.0, level: 0.4, plateau: 0.18, cut: 0.02 },\n ],\n },\n}\n\n/** iron-pulse โ ์ฐ์
sub ํํ kick(+click) + ๊ฑฐ์น highpass grit(hat). */\nexport const IRON_KIT: DrumKitPreset = {\n kick: {\n body: {\n startHz: 95,\n endHz: 38,\n pitchTau: 0.05,\n attack: 0.003,\n attackCurve: 'lin',\n decay: 0.28,\n stop: 0.35,\n },\n click: { hpHz: 2200, level: 0.35, attack: 0.001, attackCurve: 'lin', decay: 0.012, stop: 0.03 },\n },\n // grit = ๊ฑฐ์น highpass noise. open ๋ชจ๋ ์์ด closed ๋ง ํธ์ถ โ openDecay = closedDecay.\n hat: {\n hpHz: 6500,\n hpQ: 0.5,\n prCenter: 1.0,\n prSpread: 0.3,\n attack: 0.001,\n closedDecay: 0.035,\n openDecay: 0.035,\n closedLevel: 1,\n openLevel: 1,\n stopPad: 0.045,\n },\n}\n\n// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n// ๋ธ๋๊ฒ์ด์ฆ(bathedayยทsublime-hate) โ kick(+click) + snare. crash ๋ ์ธ๋ผ์ธ.\n// batheday === sublime-hate(์์ ๋์ผ). gratis ๋ ๋ณธ ์ถ์ถ ์ ์ธ(์๋ NOTE).\n// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n\n/** batheday/gratis/sublime ๊ณตํต snare โ bp1800 noise + ํผ์น envelope tone. */\nconst BLACKGAZE_SNARE: SnarePreset = {\n noise: { bpHz: 1800, q: 1.3, prMin: 1.0, prMax: 1.0, level: 0.6, decay: 0.2, stop: 0.25 },\n tone: {\n type: 'triangle',\n startHz: 260,\n endHz: 160,\n pitchTau: 0.08,\n level: 0.32,\n decay: 0.13,\n stop: 0.18,\n },\n}\n\n/** batheday โ ๋ธ๋๊ฒ์ด์ฆ ๊ณ์ด ๊ฒฐ์ kick/snare. */\nexport const BATHEDAY_KIT: DrumKitPreset = {\n kick: {\n body: {\n startHz: 150,\n endHz: 45,\n pitchTau: 0.07,\n attack: 0.004,\n attackCurve: 'lin',\n decay: 0.34,\n stop: 0.4,\n },\n click: { hpHz: 2200, level: 0.28, attack: 0.001, attackCurve: 'lin', decay: 0.01, stop: 0.03 },\n },\n snare: BLACKGAZE_SNARE,\n}\n\n/** sublime-hate โ kick/snare ๊ฐ batheday ์ ์์ ๋์ผ. */\nexport const SUBLIME_KIT: DrumKitPreset = BATHEDAY_KIT\n\n// NOTE: gratis ๋ ๋ณธ ์ถ์ถ์์ ์ ์ธ โ gratis.ts ์ ์ธ๋ผ์ธ ๋๋ผ ์ ์ง. ์น๊ฒฉ ์ GRATIS_KIT ์ถ๊ฐ\n// (kick ๋ง ๋ฏธ์ธ์ฐจ: body 140โ42, click level 0.26. snare ๋ BLACKGAZE_SNARE ๊ณตํต).\n\n/** reveal-the-truth โ IDM ๊ณ์ด์ *snappy* kick(+click) + snare + hat. */\nexport const REVEAL_KIT: DrumKitPreset = {\n kick: {\n body: {\n startHz: 140,\n endHz: 42,\n pitchTau: 0.07,\n attack: 0.004,\n attackCurve: 'lin',\n decay: 0.38,\n stop: 0.45,\n },\n click: { hpHz: 1800, level: 0.25, attack: 0.001, attackCurve: 'lin', decay: 0.01, stop: 0.03 },\n },\n snare: {\n noise: { bpHz: 1700, q: 1.4, prMin: 1.0, prMax: 1.0, level: 0.55, decay: 0.18, stop: 0.25 },\n tone: {\n type: 'triangle',\n startHz: 240,\n endHz: 150,\n pitchTau: 0.08,\n level: 0.3,\n decay: 0.12,\n stop: 0.18,\n },\n },\n hat: {\n hpHz: 7200,\n prCenter: 1.0,\n prSpread: 0.3,\n attack: 0.001,\n closedDecay: 0.025,\n openDecay: 0.12,\n closedLevel: 1,\n openLevel: 1,\n stopPad: 0.02,\n },\n}\n\n// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n// Dub(relayยทholyยทpower) โ sub tail kick(exp attack, peak>velocity) + click.\n// duck rampยทclapยทrimยทshimmer ๋ ํธ๋ ์ธ๋ผ์ธ(์์ง ๋ฐ). dub-relay/holy ๋ hat ๋ฏธ์ฌ์ฉ.\n// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n\n/** dub-relay โ 144 BPM, 2-body sub kick. */\nexport const DUB_RELAY_KIT: DrumKitPreset = {\n kick: {\n body: {\n startHz: 130,\n endHz: 48,\n pitchTau: 0.08,\n attack: 0.004,\n attackCurve: 'exp',\n peakMul: 1.3,\n decay: 0.6,\n stop: 0.65,\n },\n sub: {\n startHz: 60,\n endHz: 38,\n pitchTau: 0.12,\n attack: 0.008,\n attackCurve: 'exp',\n peakMul: 0.95,\n decay: 0.45,\n stop: 0.5,\n },\n click: { hpHz: 2500, level: 0.4, attack: 0.001, attackCurve: 'exp', decay: 0.02, stop: 0.04 },\n },\n hat: {\n hpHz: 7800,\n bpHz: 9000,\n bpQ: 0.9,\n prCenter: 1.0,\n prSpread: 0.05,\n attack: 0.002,\n closedDecay: 0.035,\n openDecay: 0.13,\n closedLevel: 0.22,\n openLevel: 0.32,\n stopPad: 0.02,\n },\n}\n\n/** dub-holy โ 70 BPM half-time, *๋ ๊น๊ณ ๊ธด* sub kick. hat ๋ฏธ์ฌ์ฉ. */\nexport const DUB_HOLY_KIT: DrumKitPreset = {\n kick: {\n body: {\n startHz: 140,\n endHz: 44,\n pitchTau: 0.1,\n attack: 0.005,\n attackCurve: 'exp',\n peakMul: 1.4,\n decay: 0.85,\n stop: 0.9,\n },\n sub: {\n startHz: 56,\n endHz: 36,\n pitchTau: 0.15,\n attack: 0.01,\n attackCurve: 'exp',\n peakMul: 1.05,\n decay: 0.7,\n stop: 0.75,\n },\n click: {\n hpHz: 2200,\n level: 0.32,\n attack: 0.0015,\n attackCurve: 'exp',\n decay: 0.025,\n stop: 0.05,\n },\n },\n}\n\n/** dub-power โ 78 BPM, *๊ถ์์ ๋ฐ* kick + hat. */\nexport const DUB_POWER_KIT: DrumKitPreset = {\n kick: {\n body: {\n startHz: 140,\n endHz: 45,\n pitchTau: 0.1,\n attack: 0.005,\n attackCurve: 'exp',\n peakMul: 1.35,\n decay: 0.75,\n stop: 0.8,\n },\n sub: {\n startHz: 64.6,\n endHz: 38,\n pitchTau: 0.15,\n attack: 0.01,\n attackCurve: 'exp',\n peakMul: 1.05,\n decay: 0.6,\n stop: 0.65,\n },\n click: { hpHz: 2200, level: 0.32, attack: 0.001, attackCurve: 'exp', decay: 0.025, stop: 0.04 },\n },\n hat: {\n hpHz: 6500,\n bpHz: 7200,\n bpQ: 0.85,\n prCenter: 1.0,\n prSpread: 0.06,\n attack: 0.002,\n closedDecay: 0.045,\n openDecay: 0.22,\n closedLevel: 0.24,\n openLevel: 0.34,\n stopPad: 0.02,\n },\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dub chamber โ dub-relayยทdub-holyยทdub-power ๊ฐ ๊ธ์ ๊ทธ๋๋ก ๋ณต์ ํ๋ *๋ง์คํฐ/๋ฏน์ค ์ฑ๋ฒ* ๋ฅผ ํ
|
|
3
|
+
* ๋ชจ๋๋ก. drumkitยทsunwall ๊ณผ ๊ฐ์ VST ๋ชจ๋ธ: `createDubChamber` ์ *์-๋ถ๋ฌธ ์ฑ๋ฒ ์์ง*,
|
|
4
|
+
* `*_CHAMBER` ์ *ํจ์น*. ์ฑ๋ฒ๋ *์ธ ๋จ์ ์ง๋ ฌ ๋ฏน์ค* ๋ง ์์ ํ๋ค โ
|
|
5
|
+
*
|
|
6
|
+
* โ ์ฌ์ด๋์ฒด์ธ ducking : kick ์ด ๋จ์ด์ง๋ฉด chordยทpadยทsub(=`ductable`)๊ฐ ์ ๊น ๋๋ฆฐ๋ค.
|
|
7
|
+
* drum/perc(=`drumBus`)๋ ์ฐํํด *์ง๊ฒฉ* ์ผ๋ก ์น๋ค.
|
|
8
|
+
* โก dub delay return : cross-feedback stereo delay โ HP+LP โ return โ ductable(๋ฅ tail ๋ ํธํก).
|
|
9
|
+
* send ๋์ *per-section automation* ์ ํธ๋์ ๋จ๋๋ค(`dubSend` ๋
ธ๋๋ง ๋
ธ์ถ).
|
|
10
|
+
* โข tape saturation : soft-clip(tanh) waveshaper โ ๋ง์คํฐ lowpass โ masterOut โ destination.
|
|
11
|
+
*
|
|
12
|
+
* ์ฑ๋ฒ ๋ฐ(ํธ๋)์ ๋จ๋ ๊ฒ: voice ํฉ์ฑ(kickยทchordยทpadยทโฆ), dubSend ์ section ๊ณก์ , 16th ์ํ์ค.
|
|
13
|
+
* 16th lookahead ๋ฃจํ๋ `../scheduler` ์ `runStepClock` ์ผ๋ก ๋ฐ๋ก ์ถ์ถ๋๋ค.
|
|
14
|
+
* ๋ณด์กด ๊ธฐ์ค: ๋
ธ๋ ํ ํด๋ก์งยท์์ ๊ทธ๋๋ก โ ์์ ์ถ์ถ.
|
|
15
|
+
*/
|
|
16
|
+
/** ๋ง์คํฐ ๋จ โ tape lowpass + soft-clip saturation. */
|
|
17
|
+
interface MasterStage {
|
|
18
|
+
/** tape lowpass ์ปท(Hz). relay/power 12k, holy 14k. */
|
|
19
|
+
lowpassHz: number;
|
|
20
|
+
/** tanh saturation drive. relay 2.4, holy 2.0, power 2.2. */
|
|
21
|
+
satDrive: number;
|
|
22
|
+
}
|
|
23
|
+
/** ๋ง์คํฐ fade in/out envelope. */
|
|
24
|
+
interface FadeStage {
|
|
25
|
+
/** 0 โ 1 ๊น์ง linear ramp ์๊ฐ(์ด). */
|
|
26
|
+
inSec: number;
|
|
27
|
+
/** ๋๋๊ธฐ `outLeadSec` ์ด ์ ๋ถํฐ exp ramp โ 0. */
|
|
28
|
+
outLeadSec: number;
|
|
29
|
+
}
|
|
30
|
+
/** kick ์ฌ์ด๋์ฒด์ธ duck โ ductable ์ ๋๋ ๋ค ๋ณต๊ท. */
|
|
31
|
+
interface DuckStage {
|
|
32
|
+
/** ๋๋ฆฌ๋ ์ต์ gain. relay 0.7(์๋ง), holy/power 0.55(๊น๊ฒ). */
|
|
33
|
+
min: number;
|
|
34
|
+
/** min ๋๋ฌ ์๊ฐ(์ด). */
|
|
35
|
+
attackSec: number;
|
|
36
|
+
/** 1.0 ๋ณต๊ท ์๋ฃ ์๊ฐ(์ด). half-time ์ผ์๋ก ๊ธธ๋ค. */
|
|
37
|
+
recoverSec: number;
|
|
38
|
+
}
|
|
39
|
+
/** dub delay return โ cross-feedback stereo delay + HP/LP tail. */
|
|
40
|
+
interface DelayStage {
|
|
41
|
+
/** DelayNode maxDelayTime. */
|
|
42
|
+
maxSec: number;
|
|
43
|
+
/** L delay(์ ์ 8๋ถ), R delay(4๋ถ). */
|
|
44
|
+
timeL: number;
|
|
45
|
+
timeR: number;
|
|
46
|
+
/** cross feedback gain. */
|
|
47
|
+
feedback: number;
|
|
48
|
+
/** tail HP(sub ๋ถ๋ฆฌ) / LP(dark dub). */
|
|
49
|
+
hpHz: number;
|
|
50
|
+
lpHz: number;
|
|
51
|
+
/** return gain โ ๋๊ป. */
|
|
52
|
+
returnGain: number;
|
|
53
|
+
}
|
|
54
|
+
interface DubChamberPreset {
|
|
55
|
+
master: MasterStage;
|
|
56
|
+
fade: FadeStage;
|
|
57
|
+
duck: DuckStage;
|
|
58
|
+
delay: DelayStage;
|
|
59
|
+
}
|
|
60
|
+
interface DubChamber {
|
|
61
|
+
/** chordยทpadยทsubยทreese ๊ฐ ๋ชจ์ด๋ *ducked* bus. */
|
|
62
|
+
readonly ductable: GainNode;
|
|
63
|
+
/** drumยทperc ๊ฐ ๋ชจ์ด๋ *duck ์ฐํ* bus. */
|
|
64
|
+
readonly drumBus: GainNode;
|
|
65
|
+
/** dub delay send. ํธ๋์ด section ๋ณ๋ก gain automation. */
|
|
66
|
+
readonly dubSend: GainNode;
|
|
67
|
+
/** kick ๋ง๋ค ํธ์ถ โ ductable ์ ๋๋ ๋ค ๋ณต๊ท(์ฌ์ด๋์ฒด์ธ). */
|
|
68
|
+
duck(when: number): void;
|
|
69
|
+
/** ๋ง์คํฐ fade in/out ์ ํ ๋ฒ์ ์ค์ผ์ค. start=๊ทธ๋ฆฌ๋ ์์ , totalSec=๊ณก ๊ธธ์ด. */
|
|
70
|
+
open(start: number, totalSec: number): void;
|
|
71
|
+
/** teardown โ ๋น ๋ฅธ fade out ํ 250 ms ๋ค ์ฑ๋ฒ ๋
ธ๋ ์ ๋ถ disconnect. */
|
|
72
|
+
dispose(): void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* dub ๋ง์คํฐ/๋ฏน์ค ์ฑ๋ฒ๋ฅผ ๋ง๋ค์ด ํธ๋ค์ ๋๋ ค์ค๋ค. ํธ๋ voice ๋ `ductable`ยท`drumBus`ยท`dubSend`
|
|
76
|
+
* ์ ์ฐ๊ฒฐํ๊ณ , kick ๋ง๋ค `duck(when)`, ์์์ `open(start, total)`, teardown ์ `dispose()`.
|
|
77
|
+
*
|
|
78
|
+
* @param destination ํธ๋ score ๊ฐ ๋ฐ์ ์ต์ข
๋ชฉ์ ์ง(AudioContext.destination ๋ฑ).
|
|
79
|
+
*/
|
|
80
|
+
declare function createDubChamber(ctx: AudioContext, destination: AudioNode, preset: DubChamberPreset): DubChamber;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Dub chamber presets โ *์ฑ๋ฒ ํจ์น*. ํธ๋๋น ํ๋. ๊ฐ dub ํธ๋ ์ธ๋ผ์ธ ๋ง์คํฐ/๋ฏน์ค ์ฑ๋ฒ์ *๋ค๋ฆฌ๋
|
|
84
|
+
* ์์* ๋ฅผ ๊ทธ๋๋ก ์ฎ๊ธด ๊ฒ์ด๋ผ, ๊ฑฐ์ ๊ฐ์ ๋ณด์ฌ๋ ํฉ์น์ง ์๋๋ค โ *์๋ฆฌ ๋ณด์กด* ์ด ๊ธฐ์ค.
|
|
85
|
+
* dedup ์ด๋์ ์์ง(`createDubChamber`)์ด์ง preset ์๊ฐ ์๋๋ค.
|
|
86
|
+
*
|
|
87
|
+
* delay time ์ *BPM ์ ์ ์ 8๋ถ/4๋ถ* ์ด๋ผ ํธ๋๋ง๋ค ๋ค๋ฅด๋ค(144 / 70 / 78 BPM).
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
/** dub-relay โ 144 BPM. ์์ duck(0.7, ๋ฒ ์ด์ค *์ง์ ์๋ ฅ*) + ์งง์ 313 ms echo. */
|
|
91
|
+
declare const DUB_RELAY_CHAMBER: DubChamberPreset;
|
|
92
|
+
/** dub-holy โ 70 BPM half-time. *๊น๊ณ ๊ธด* duck(0.55 / 0.45 s) + 643 ms ๋๊บผ์ด echo. */
|
|
93
|
+
declare const DUB_HOLY_CHAMBER: DubChamberPreset;
|
|
94
|
+
/** dub-power โ 78 BPM. ๊น๊ณ ๊ธด duck(0.55 / 0.32 s) + 577 ms *๊ถ์์ ์ํฅ*. */
|
|
95
|
+
declare const DUB_POWER_CHAMBER: DubChamberPreset;
|
|
96
|
+
/**
|
|
97
|
+
* crush(22) โ 66 BPM sludge. *์ธ ์์ง ๋์ ์ต๋์น* ์ ๋ง์คํฐ(๋ฒฝ ํฌ๋ ์
ด๋ + ์ ๋ฐ + ๋ฅ ์ํฅ).
|
|
98
|
+
* ๊ฐ์ฅ ๊ฑฐ์น saturation(2.6) + ๊ฐ์ฅ ์ด๋์ด LP(8000) โ ๊ฒ์ ๋ฒฝ์ ๊ฑฐ์น ๊ณ ์ญ์ ํ ๊ฒน ๋ ๊น๋๋ค.
|
|
99
|
+
* duck ์ ์๊ฒ(0.6) โ *์ * kick ์ด ๋ฒฝ์ ๋ซ๋ ๋ฒฝ์ ๋ฌด๋๋จ๋ฆฌ์ง ์๊ฒ. 682 ms *์ง๋๋ฅด๋* dub tail.
|
|
100
|
+
*/
|
|
101
|
+
declare const CRUSH_CHAMBER: DubChamberPreset;
|
|
102
|
+
|
|
103
|
+
export { CRUSH_CHAMBER, DUB_HOLY_CHAMBER, DUB_POWER_CHAMBER, DUB_RELAY_CHAMBER, type DelayStage, type DubChamber, type DubChamberPreset, type DuckStage, type FadeStage, type MasterStage, createDubChamber };
|