@jpdutoit/squelchy 0.0.5 → 0.0.6
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 -0
- package/{chunk-N7J25N5J.js → chunk-PJDNZ52Q.js} +21 -5
- package/chunk-PJDNZ52Q.js.map +7 -0
- package/docs/GUIDE.md +27 -4
- package/docs/MODULES.md +46 -36
- package/docs/modules.json +113 -31
- package/index.d.ts +75 -25
- package/index.js +526 -350
- package/index.js.map +3 -3
- package/kits/compu-78/bd.flac +0 -0
- package/kits/compu-78/ch.flac +0 -0
- package/kits/compu-78/clap.flac +0 -0
- package/kits/compu-78/cym.flac +0 -0
- package/kits/compu-78/ht.flac +0 -0
- package/kits/compu-78/lt.flac +0 -0
- package/kits/compu-78/mt.flac +0 -0
- package/kits/compu-78/oh.flac +0 -0
- package/kits/compu-78/perc.flac +0 -0
- package/kits/compu-78/rim.flac +0 -0
- package/kits/compu-78/sd.flac +0 -0
- package/kits/deep-analogue/bd.flac +0 -0
- package/kits/deep-analogue/ch.flac +0 -0
- package/kits/deep-analogue/clap.flac +0 -0
- package/kits/deep-analogue/cym.flac +0 -0
- package/kits/deep-analogue/ht.flac +0 -0
- package/kits/deep-analogue/lt.flac +0 -0
- package/kits/deep-analogue/mt.flac +0 -0
- package/kits/deep-analogue/oh.flac +0 -0
- package/kits/deep-analogue/perc.flac +0 -0
- package/kits/deep-analogue/rim.flac +0 -0
- package/kits/deep-analogue/sd.flac +0 -0
- package/kits/hard-cell/bd.flac +0 -0
- package/kits/hard-cell/ch.flac +0 -0
- package/kits/hard-cell/clap.flac +0 -0
- package/kits/hard-cell/cym.flac +0 -0
- package/kits/hard-cell/ht.flac +0 -0
- package/kits/hard-cell/lt.flac +0 -0
- package/kits/hard-cell/mt.flac +0 -0
- package/kits/hard-cell/oh.flac +0 -0
- package/kits/hard-cell/perc.flac +0 -0
- package/kits/hard-cell/rim.flac +0 -0
- package/kits/hard-cell/sd.flac +0 -0
- package/kits/micro-click/bd.flac +0 -0
- package/kits/micro-click/ch.flac +0 -0
- package/kits/micro-click/clap.flac +0 -0
- package/kits/micro-click/cym.flac +0 -0
- package/kits/micro-click/ht.flac +0 -0
- package/kits/micro-click/lt.flac +0 -0
- package/kits/micro-click/mt.flac +0 -0
- package/kits/micro-click/oh.flac +0 -0
- package/kits/micro-click/perc.flac +0 -0
- package/kits/micro-click/rim.flac +0 -0
- package/kits/micro-click/sd.flac +0 -0
- package/kits/tape-dust/bd.flac +0 -0
- package/kits/tape-dust/ch.flac +0 -0
- package/kits/tape-dust/clap.flac +0 -0
- package/kits/tape-dust/cym.flac +0 -0
- package/kits/tape-dust/ht.flac +0 -0
- package/kits/tape-dust/lt.flac +0 -0
- package/kits/tape-dust/mt.flac +0 -0
- package/kits/tape-dust/oh.flac +0 -0
- package/kits/tape-dust/perc.flac +0 -0
- package/kits/tape-dust/rim.flac +0 -0
- package/kits/tape-dust/sd.flac +0 -0
- package/package.json +1 -1
- package/{worklets-inline-EF3OTQ4D.js → worklets-inline-NWG5PWND.js} +10 -2
- package/{worklets-inline-EF3OTQ4D.js.map → worklets-inline-NWG5PWND.js.map} +2 -2
- package/chunk-N7J25N5J.js.map +0 -7
package/index.js
CHANGED
|
@@ -2,12 +2,14 @@ import {
|
|
|
2
2
|
adsr_envelope_default,
|
|
3
3
|
bitcrusher_default,
|
|
4
4
|
comb_filter_default,
|
|
5
|
+
compressor_default,
|
|
5
6
|
env_follower_default,
|
|
6
7
|
fdn_reverb_default,
|
|
7
8
|
flanger_default,
|
|
8
9
|
formant_table_default,
|
|
9
10
|
freq_divider_default,
|
|
10
11
|
freq_shifter_default,
|
|
12
|
+
gate_default,
|
|
11
13
|
glide_default,
|
|
12
14
|
ladder_filter_default,
|
|
13
15
|
map_res_default,
|
|
@@ -15,12 +17,14 @@ import {
|
|
|
15
17
|
map_voct_to_period_default,
|
|
16
18
|
ping_pong_default,
|
|
17
19
|
pitch_shifter_default,
|
|
20
|
+
shaper_default,
|
|
18
21
|
spring_reverb_default,
|
|
19
22
|
tape_delay_default,
|
|
20
23
|
tape_stop_default,
|
|
21
24
|
vca_default,
|
|
25
|
+
vinyl_noise_default,
|
|
22
26
|
waveshaper_default
|
|
23
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-PJDNZ52Q.js";
|
|
24
28
|
|
|
25
29
|
// src/lib-runtime/core.ts
|
|
26
30
|
var pendingSources = {};
|
|
@@ -28,7 +32,7 @@ var registrations = /* @__PURE__ */ new WeakMap();
|
|
|
28
32
|
function preload(ctx, opts) {
|
|
29
33
|
const existing = registrations.get(ctx);
|
|
30
34
|
if (existing) return existing;
|
|
31
|
-
const sources = opts?.allWorklets ? import("./worklets-inline-
|
|
35
|
+
const sources = opts?.allWorklets ? import("./worklets-inline-NWG5PWND.js").then((m) => m.WORKLET_SOURCES) : Promise.resolve(pendingSources);
|
|
32
36
|
const promise = sources.then(
|
|
33
37
|
(map) => Promise.all(Object.entries(map).map(async ([name, src]) => {
|
|
34
38
|
const url = URL.createObjectURL(new Blob([src], { type: "text/javascript" }));
|
|
@@ -502,20 +506,27 @@ var NoteCv = {
|
|
|
502
506
|
const pitch = ctx.createConstantSource();
|
|
503
507
|
pitch.offset.value = 60;
|
|
504
508
|
pitch.start();
|
|
509
|
+
const velocity = ctx.createConstantSource();
|
|
510
|
+
velocity.offset.value = 0;
|
|
511
|
+
velocity.start();
|
|
505
512
|
return {
|
|
506
513
|
gate,
|
|
507
514
|
pitch,
|
|
515
|
+
velocity,
|
|
508
516
|
trigger(time, h) {
|
|
509
517
|
if (typeof h?.value === "number") pitch.offset.setValueAtTime(h.value, time);
|
|
510
|
-
|
|
511
|
-
|
|
518
|
+
velocity.offset.setValueAtTime(vel(h), time);
|
|
519
|
+
const edge = Math.max(0, time - 1 / ctx.sampleRate);
|
|
520
|
+
gate.offset.cancelScheduledValues(edge);
|
|
521
|
+
gate.offset.setValueAtTime(0, edge);
|
|
522
|
+
gate.offset.setValueAtTime(1, time);
|
|
512
523
|
gate.offset.setValueAtTime(0, time + (h?.duration ?? 0.1));
|
|
513
524
|
},
|
|
514
525
|
dispose() {
|
|
515
|
-
gate
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
526
|
+
for (const n of [gate, pitch, velocity]) {
|
|
527
|
+
n.stop();
|
|
528
|
+
n.disconnect();
|
|
529
|
+
}
|
|
519
530
|
}
|
|
520
531
|
};
|
|
521
532
|
}
|
|
@@ -698,14 +709,33 @@ function createFormantNode(ctx) {
|
|
|
698
709
|
return new AudioWorkletNode(ctx, "formant-table", {
|
|
699
710
|
numberOfInputs: 1,
|
|
700
711
|
numberOfOutputs: 1,
|
|
701
|
-
outputChannelCount: [
|
|
712
|
+
outputChannelCount: [11]
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
function createShaperNode(ctx, curve, opts = {}) {
|
|
716
|
+
return new AudioWorkletNode(ctx, "shaper", {
|
|
717
|
+
numberOfInputs: 2,
|
|
718
|
+
numberOfOutputs: 2,
|
|
719
|
+
channelCount: 2,
|
|
720
|
+
channelCountMode: "clamped-max",
|
|
721
|
+
outputChannelCount: [2, 2],
|
|
722
|
+
processorOptions: { curve, dry: opts.dry !== false }
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
function createVinylNoiseNode(ctx, seed) {
|
|
726
|
+
return new AudioWorkletNode(ctx, "vinyl-noise", {
|
|
727
|
+
numberOfInputs: 0,
|
|
728
|
+
numberOfOutputs: 1,
|
|
729
|
+
outputChannelCount: [1],
|
|
730
|
+
processorOptions: { seed }
|
|
702
731
|
});
|
|
703
732
|
}
|
|
704
733
|
function createBitcrusherNode(ctx) {
|
|
705
734
|
return new AudioWorkletNode(ctx, "bitcrusher", {
|
|
706
735
|
numberOfInputs: 1,
|
|
707
736
|
numberOfOutputs: 1,
|
|
708
|
-
|
|
737
|
+
channelCount: 2,
|
|
738
|
+
channelCountMode: "clamped-max"
|
|
709
739
|
});
|
|
710
740
|
}
|
|
711
741
|
function createSubOctaveNode(ctx) {
|
|
@@ -722,6 +752,27 @@ function createEnvFollowerNode(ctx) {
|
|
|
722
752
|
outputChannelCount: [1]
|
|
723
753
|
});
|
|
724
754
|
}
|
|
755
|
+
function createGateNode(ctx) {
|
|
756
|
+
return new AudioWorkletNode(ctx, "gate", {
|
|
757
|
+
numberOfInputs: 2,
|
|
758
|
+
numberOfOutputs: 1,
|
|
759
|
+
outputChannelCount: [2],
|
|
760
|
+
channelCount: 2,
|
|
761
|
+
channelCountMode: "clamped-max",
|
|
762
|
+
channelInterpretation: "speakers"
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
function createCompressorNode(ctx, init) {
|
|
766
|
+
return new AudioWorkletNode(ctx, "compressor", {
|
|
767
|
+
numberOfInputs: 2,
|
|
768
|
+
numberOfOutputs: 1,
|
|
769
|
+
outputChannelCount: [2],
|
|
770
|
+
channelCount: 2,
|
|
771
|
+
channelCountMode: "clamped-max",
|
|
772
|
+
channelInterpretation: "speakers",
|
|
773
|
+
parameterData: init
|
|
774
|
+
});
|
|
775
|
+
}
|
|
725
776
|
function createWaveshaperNode(ctx) {
|
|
726
777
|
return new AudioWorkletNode(ctx, "waveshaper", {
|
|
727
778
|
numberOfInputs: 1,
|
|
@@ -927,7 +978,7 @@ var filter303Descriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
927
978
|
const envDepth = ctx.createGain();
|
|
928
979
|
envDepth.gain.value = module.envMod * (1 + module.accent) * 36;
|
|
929
980
|
const accentEnvGain = ctx.createGain();
|
|
930
|
-
accentEnvGain.gain.value = module.accent *
|
|
981
|
+
accentEnvGain.gain.value = module.accent * 1;
|
|
931
982
|
input.connect(filter1);
|
|
932
983
|
filter1.connect(filter2);
|
|
933
984
|
filter2.connect(accentVCA);
|
|
@@ -957,7 +1008,7 @@ var filter303Descriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
957
1008
|
case "accent": {
|
|
958
1009
|
const acc = value;
|
|
959
1010
|
nodes.envDepth.gain.value = module.envMod * (1 + acc) * 36;
|
|
960
|
-
nodes.accentEnvGain.gain.value = acc *
|
|
1011
|
+
nodes.accentEnvGain.gain.value = acc * 1;
|
|
961
1012
|
break;
|
|
962
1013
|
}
|
|
963
1014
|
case "decay": {
|
|
@@ -983,8 +1034,9 @@ var AcidFilter = /* @__PURE__ */ defineModule(filter303Descriptor, {
|
|
|
983
1034
|
|
|
984
1035
|
// src/lib-runtime/generated/modules/auto-pan.tsx
|
|
985
1036
|
var shapes = ["sine", "triangle", "square"];
|
|
1037
|
+
var SHAPE_VALUE = { square: -1, triangle: 0, sine: 1 };
|
|
986
1038
|
var params2 = {
|
|
987
|
-
rate: { node: "
|
|
1039
|
+
rate: { node: "_freqSrc", field: "offset", unit: "Hz", default: 2, min: 0.1, max: 10 },
|
|
988
1040
|
depth: { node: "lfoGain", field: "gain", unit: "factor", default: 0.8, min: 0, max: 1 },
|
|
989
1041
|
shape: { kind: "enum", options: shapes, default: "sine" }
|
|
990
1042
|
};
|
|
@@ -994,7 +1046,7 @@ var autoPanDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
994
1046
|
ports: {
|
|
995
1047
|
"in": { type: "input", signal: "audio", node: "input" },
|
|
996
1048
|
"out": { type: "output", signal: "audio", node: "output" },
|
|
997
|
-
"modRate": { type: "modulation", signal: "modulation", node: "
|
|
1049
|
+
"modRate": { type: "modulation", signal: "modulation", node: "_freqSrc", field: "offset" },
|
|
998
1050
|
"modDepth": { type: "modulation", signal: "modulation", node: "lfoGain", field: "gain" }
|
|
999
1051
|
},
|
|
1000
1052
|
createModule(id, position) {
|
|
@@ -1004,34 +1056,41 @@ var autoPanDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1004
1056
|
const input = ctx.createGain();
|
|
1005
1057
|
const panner = ctx.createStereoPanner();
|
|
1006
1058
|
const output = ctx.createGain();
|
|
1007
|
-
const
|
|
1059
|
+
const _ws = createWaveshaperNode(ctx);
|
|
1060
|
+
const _freqSrc = ctx.createConstantSource();
|
|
1061
|
+
_freqSrc.offset.value = module.rate;
|
|
1062
|
+
_freqSrc.start();
|
|
1063
|
+
_freqSrc.connect(_ws);
|
|
1064
|
+
_ws.parameters.get("skew").value = 0;
|
|
1065
|
+
_ws.parameters.get("shape").value = SHAPE_VALUE[module.shape];
|
|
1008
1066
|
const lfoGain = ctx.createGain();
|
|
1009
|
-
lfo.type = module.shape;
|
|
1010
|
-
lfo.frequency.value = module.rate;
|
|
1011
1067
|
lfoGain.gain.value = module.depth;
|
|
1012
|
-
|
|
1068
|
+
_ws.connect(lfoGain);
|
|
1013
1069
|
lfoGain.connect(panner.pan);
|
|
1014
|
-
lfo.start();
|
|
1015
1070
|
input.connect(panner);
|
|
1016
1071
|
panner.connect(output);
|
|
1017
|
-
return { input, output,
|
|
1072
|
+
return { input, output, _ws, _freqSrc, lfoGain };
|
|
1018
1073
|
},
|
|
1019
1074
|
updateParam(nodes, _m, param, value) {
|
|
1020
1075
|
if (param === "rate") {
|
|
1021
|
-
nodes.
|
|
1076
|
+
nodes._freqSrc.offset.value = value;
|
|
1022
1077
|
} else if (param === "depth") {
|
|
1023
1078
|
nodes.lfoGain.gain.value = value;
|
|
1024
1079
|
} else if (param === "shape") {
|
|
1025
|
-
nodes.
|
|
1080
|
+
nodes._ws.parameters.get("shape").value = SHAPE_VALUE[value];
|
|
1026
1081
|
}
|
|
1027
1082
|
},
|
|
1028
1083
|
dispose(nodes) {
|
|
1029
|
-
nodes.
|
|
1084
|
+
nodes._freqSrc.stop();
|
|
1030
1085
|
}
|
|
1031
1086
|
});
|
|
1032
1087
|
|
|
1033
1088
|
// src/lib-runtime/generated/modules/auto-pan.wrapper.ts
|
|
1034
|
-
var AutoPan = /* @__PURE__ */ defineModule(autoPanDescriptor
|
|
1089
|
+
var AutoPan = /* @__PURE__ */ defineModule(autoPanDescriptor, {
|
|
1090
|
+
worklets: {
|
|
1091
|
+
"waveshaper": waveshaper_default
|
|
1092
|
+
}
|
|
1093
|
+
});
|
|
1035
1094
|
|
|
1036
1095
|
// src/lib/dsp/mix.ts
|
|
1037
1096
|
var CURVE_POINTS = 2049;
|
|
@@ -1083,7 +1142,10 @@ var bitcrusherDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1083
1142
|
params: params3,
|
|
1084
1143
|
ports: {
|
|
1085
1144
|
"in": { type: "input", signal: "audio", node: "input" },
|
|
1086
|
-
"out": { type: "output", signal: "audio", node: "output" }
|
|
1145
|
+
"out": { type: "output", signal: "audio", node: "output" },
|
|
1146
|
+
"modBits": { type: "modulation", signal: "modulation", node: "crusher", field: "bits" },
|
|
1147
|
+
"modRate": { type: "modulation", signal: "modulation", node: "crusher", field: "rate" },
|
|
1148
|
+
"modMix": { type: "modulation", signal: "modulation", node: "_mix", field: "offset" }
|
|
1087
1149
|
},
|
|
1088
1150
|
createModule(id, position) {
|
|
1089
1151
|
return { id, type: "bitcrusher", position, ...paramDefaults(params3) };
|
|
@@ -1124,6 +1186,8 @@ var Bitcrusher = /* @__PURE__ */ defineModule(bitcrusherDescriptor, {
|
|
|
1124
1186
|
});
|
|
1125
1187
|
|
|
1126
1188
|
// src/lib-runtime/generated/modules/chorus.tsx
|
|
1189
|
+
var CENTRE_S = 566e-5;
|
|
1190
|
+
var SWING_S = 4e-3;
|
|
1127
1191
|
var params4 = {
|
|
1128
1192
|
rate: { node: "lfo", field: "frequency", unit: "Hz", default: 1.5, min: 0.1, max: 5 },
|
|
1129
1193
|
depth: { unit: "factor", default: 0.5, min: 0, max: 1 },
|
|
@@ -1156,8 +1220,8 @@ var chorusDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1156
1220
|
const lfoGain = ctx.createGain();
|
|
1157
1221
|
const lfoInv = ctx.createGain();
|
|
1158
1222
|
const merger = ctx.createChannelMerger(2);
|
|
1159
|
-
delayL.delayTime.value =
|
|
1160
|
-
delayR.delayTime.value =
|
|
1223
|
+
delayL.delayTime.value = CENTRE_S;
|
|
1224
|
+
delayR.delayTime.value = CENTRE_S;
|
|
1161
1225
|
const _mix = ctx.createConstantSource();
|
|
1162
1226
|
_mix.offset.value = module.mix;
|
|
1163
1227
|
dryGain.gain.value = 1;
|
|
@@ -1169,7 +1233,7 @@ var chorusDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1169
1233
|
_mix.start();
|
|
1170
1234
|
lfo.type = "sine";
|
|
1171
1235
|
lfo.frequency.value = module.rate;
|
|
1172
|
-
lfoGain.gain.value = module.depth *
|
|
1236
|
+
lfoGain.gain.value = module.depth * SWING_S;
|
|
1173
1237
|
lfoInv.gain.value = -1;
|
|
1174
1238
|
lfo.connect(lfoGain);
|
|
1175
1239
|
lfoGain.connect(delayL.delayTime);
|
|
@@ -1193,7 +1257,7 @@ var chorusDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1193
1257
|
nodes.lfo.frequency.value = value;
|
|
1194
1258
|
break;
|
|
1195
1259
|
case "depth":
|
|
1196
|
-
nodes.lfoGain.gain.value = value *
|
|
1260
|
+
nodes.lfoGain.gain.value = value * SWING_S;
|
|
1197
1261
|
break;
|
|
1198
1262
|
case "mix":
|
|
1199
1263
|
nodes._mix.offset.value = value;
|
|
@@ -1306,62 +1370,59 @@ var CombFilter = /* @__PURE__ */ defineModule(combFilterDescriptor, {
|
|
|
1306
1370
|
var params6 = {
|
|
1307
1371
|
threshold: { node: "comp", field: "threshold", unit: "dB", default: -24, min: -60, max: 0 },
|
|
1308
1372
|
ratio: { node: "comp", field: "ratio", unit: "factor", default: 4, min: 1, max: 20, scale: "log" },
|
|
1309
|
-
attack: { node: "comp", field: "attack", unit: "s", default: 3e-3, min: 1e-
|
|
1373
|
+
attack: { node: "comp", field: "attack", unit: "s", default: 3e-3, min: 1e-4, max: 1, scale: "log" },
|
|
1310
1374
|
release: { node: "comp", field: "release", unit: "s", default: 0.25, min: 0.01, max: 1, scale: "log" },
|
|
1311
1375
|
knee: { node: "comp", field: "knee", unit: "dB", default: 10, min: 0, max: 40 },
|
|
1312
|
-
|
|
1313
|
-
// not
|
|
1314
|
-
|
|
1376
|
+
makeup: { node: "comp", field: "makeup", unit: "dB", default: 0, min: 0, max: 30 },
|
|
1377
|
+
// A switch, not jack sensing: the browser reports an input as empty
|
|
1378
|
+
// whenever its source stops (e.g. between drum samples). See compressor.ts.
|
|
1379
|
+
keySource: { kind: "enum", options: ["internal", "external"], default: "internal" }
|
|
1315
1380
|
};
|
|
1316
1381
|
var compressorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
1317
1382
|
type: "compressor",
|
|
1318
1383
|
params: params6,
|
|
1319
1384
|
ports: {
|
|
1320
1385
|
"in": { type: "input", signal: "audio", node: "comp" },
|
|
1321
|
-
"
|
|
1386
|
+
"key": { type: "input", signal: "audio", node: "_keyIn" },
|
|
1387
|
+
"out": { type: "output", signal: "audio", node: "comp" }
|
|
1322
1388
|
},
|
|
1323
1389
|
createModule(id, position) {
|
|
1324
|
-
return { id, type: "compressor", position, ...paramDefaults(params6) };
|
|
1390
|
+
return { id, type: "compressor", position, timeUnit: "tau", ...paramDefaults(params6) };
|
|
1325
1391
|
},
|
|
1392
|
+
// One worklet does detection, gain computing, smoothing and makeup — every
|
|
1393
|
+
// knob is one of its AudioParams, 1:1. See src/worklets/compressor.ts.
|
|
1326
1394
|
createNodes(ctx, module) {
|
|
1327
|
-
const comp = ctx
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1395
|
+
const comp = createCompressorNode(ctx, {
|
|
1396
|
+
threshold: module.threshold,
|
|
1397
|
+
ratio: module.ratio,
|
|
1398
|
+
attack: module.attack,
|
|
1399
|
+
release: module.release,
|
|
1400
|
+
knee: module.knee,
|
|
1401
|
+
makeup: module.makeup ?? 0,
|
|
1402
|
+
keyExt: module.keySource === "external" ? 1 : 0
|
|
1403
|
+
});
|
|
1404
|
+
const _keyIn = ctx.createGain();
|
|
1405
|
+
_keyIn.channelCount = 2;
|
|
1406
|
+
_keyIn.channelCountMode = "clamped-max";
|
|
1407
|
+
_keyIn.connect(comp, 0, 1);
|
|
1408
|
+
return { comp, _keyIn };
|
|
1337
1409
|
},
|
|
1338
1410
|
updateParam(nodes, _m, param, value) {
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
nodes.comp.threshold.value = v;
|
|
1343
|
-
break;
|
|
1344
|
-
case "ratio":
|
|
1345
|
-
nodes.comp.ratio.value = v;
|
|
1346
|
-
break;
|
|
1347
|
-
case "attack":
|
|
1348
|
-
nodes.comp.attack.value = v;
|
|
1349
|
-
break;
|
|
1350
|
-
case "release":
|
|
1351
|
-
nodes.comp.release.value = v;
|
|
1352
|
-
break;
|
|
1353
|
-
case "knee":
|
|
1354
|
-
nodes.comp.knee.value = v;
|
|
1355
|
-
break;
|
|
1356
|
-
case "makeup":
|
|
1357
|
-
nodes.makeup.gain.value = Math.pow(10, v / 20);
|
|
1358
|
-
break;
|
|
1411
|
+
if (param === "keySource") {
|
|
1412
|
+
nodes.comp.parameters.get("keyExt").value = value === "external" ? 1 : 0;
|
|
1413
|
+
return;
|
|
1359
1414
|
}
|
|
1415
|
+
const p = nodes.comp.parameters.get(param);
|
|
1416
|
+
if (p) p.value = value;
|
|
1360
1417
|
}
|
|
1361
1418
|
});
|
|
1362
1419
|
|
|
1363
1420
|
// src/lib-runtime/generated/modules/comp.wrapper.ts
|
|
1364
|
-
var Compressor = /* @__PURE__ */ defineModule(compressorDescriptor
|
|
1421
|
+
var Compressor = /* @__PURE__ */ defineModule(compressorDescriptor, {
|
|
1422
|
+
worklets: {
|
|
1423
|
+
"compressor": compressor_default
|
|
1424
|
+
}
|
|
1425
|
+
});
|
|
1365
1426
|
|
|
1366
1427
|
// src/lib-runtime/generated/modules/crossfade.tsx
|
|
1367
1428
|
var params7 = {
|
|
@@ -1488,7 +1549,19 @@ var Delay = /* @__PURE__ */ defineModule(delayDescriptor, {
|
|
|
1488
1549
|
});
|
|
1489
1550
|
|
|
1490
1551
|
// src/lib-runtime/generated/modules/dimension.tsx
|
|
1552
|
+
var CENTER_S = 35e-4;
|
|
1553
|
+
var SWING_S2 = 185e-5;
|
|
1554
|
+
var WET = 0.5;
|
|
1555
|
+
var CROSS_HPF_HZ = 200;
|
|
1556
|
+
var BUTTERWORTH_Q_DB = -3.0102999566;
|
|
1557
|
+
function setWidth(n, w) {
|
|
1558
|
+
n.llGain.gain.value = (1 + w) / 2;
|
|
1559
|
+
n.rrGain.gain.value = (1 + w) / 2;
|
|
1560
|
+
n.rlGain.gain.value = (1 - w) / 2;
|
|
1561
|
+
n.lrGain.gain.value = (1 - w) / 2;
|
|
1562
|
+
}
|
|
1491
1563
|
var params9 = {
|
|
1564
|
+
width: { unit: "factor", default: 1.5, min: 0, max: 2 },
|
|
1492
1565
|
rate: { node: "lfo", field: "frequency", unit: "Hz", default: 0.5, min: 0.1, max: 5 },
|
|
1493
1566
|
depth: { unit: "factor", default: 0.3, min: 0, max: 1 }
|
|
1494
1567
|
};
|
|
@@ -1503,6 +1576,24 @@ var dimensionDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1503
1576
|
createModule(id, position) {
|
|
1504
1577
|
return { id, type: "dimension", position, ...paramDefaults(params9) };
|
|
1505
1578
|
},
|
|
1579
|
+
// Roland SDD-320 topology (Haible's service-schematic description, HSR 1984
|
|
1580
|
+
// review, pendragon-andyh's Juno-60 BBD analysis — see
|
|
1581
|
+
// reports/expectations/discussion/dimension.md): the dry signal anchors
|
|
1582
|
+
// both outputs; each BBD line is mixed in phase into its own channel and
|
|
1583
|
+
// inverted into the other, with the low end kept out of the cancellation.
|
|
1584
|
+
// Two short BBD-range lines (1.65–5.35 ms at full DEPTH) swept by ONE
|
|
1585
|
+
// triangle LFO in antiphase. Written out, that matrix is
|
|
1586
|
+
// A = dry_L + WET·HP(bbdA − bbdB), B = dry_R − WET·HP(bbdA − bbdB)
|
|
1587
|
+
// i.e. the moving DIFFERENCE of the two lines becomes side signal. Nothing
|
|
1588
|
+
// reaches the mid, so there is no vibrato and the mono sum is exactly the
|
|
1589
|
+
// dry input (the hardware's famed mono compatibility); the bass stays dry
|
|
1590
|
+
// and centred. HP is a Linkwitz-Riley 4th-order low-cut at 200 Hz; since
|
|
1591
|
+
// the side enters A and B in opposite polarity, the mono sum cancels it
|
|
1592
|
+
// whatever its phase, so a steep filter costs no mono compatibility.
|
|
1593
|
+
// Previously the module was 100% wet — two 10/12 ms modulated delays, i.e.
|
|
1594
|
+
// a stereo vibrato with 10 ms of latency and nothing anchoring pitch.
|
|
1595
|
+
// WIDTH then scales the side of (A, B): L = M + w·S, R = M − w·S, so
|
|
1596
|
+
// 0 = mono, 1 = the hardware matrix, 2 = exaggerated.
|
|
1506
1597
|
createNodes(ctx, module) {
|
|
1507
1598
|
const input = ctx.createGain();
|
|
1508
1599
|
input.channelCount = 2;
|
|
@@ -1516,51 +1607,62 @@ var dimensionDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1516
1607
|
const lfo = ctx.createOscillator();
|
|
1517
1608
|
const lfoGainL = ctx.createGain();
|
|
1518
1609
|
const lfoGainR = ctx.createGain();
|
|
1610
|
+
const invB = ctx.createGain();
|
|
1611
|
+
invB.gain.value = -1;
|
|
1612
|
+
const diff = ctx.createGain();
|
|
1613
|
+
const hp1 = ctx.createBiquadFilter();
|
|
1614
|
+
hp1.type = "highpass";
|
|
1615
|
+
hp1.frequency.value = CROSS_HPF_HZ;
|
|
1616
|
+
hp1.Q.value = BUTTERWORTH_Q_DB;
|
|
1617
|
+
const hp2 = ctx.createBiquadFilter();
|
|
1618
|
+
hp2.type = "highpass";
|
|
1619
|
+
hp2.frequency.value = CROSS_HPF_HZ;
|
|
1620
|
+
hp2.Q.value = BUTTERWORTH_Q_DB;
|
|
1621
|
+
const side = ctx.createGain();
|
|
1622
|
+
side.gain.value = WET;
|
|
1623
|
+
const sideInv = ctx.createGain();
|
|
1624
|
+
sideInv.gain.value = -1;
|
|
1625
|
+
const aSum = ctx.createGain();
|
|
1626
|
+
const bSum = ctx.createGain();
|
|
1519
1627
|
const llGain = ctx.createGain();
|
|
1520
1628
|
const lrGain = ctx.createGain();
|
|
1521
1629
|
const rlGain = ctx.createGain();
|
|
1522
1630
|
const rrGain = ctx.createGain();
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
lrGain.gain.value = (1 - w) / 2;
|
|
1528
|
-
leftDelay.delayTime.value = 0.01;
|
|
1529
|
-
rightDelay.delayTime.value = 0.012;
|
|
1530
|
-
lfo.type = "sine";
|
|
1631
|
+
setWidth({ llGain, lrGain, rlGain, rrGain }, module.width);
|
|
1632
|
+
leftDelay.delayTime.value = CENTER_S;
|
|
1633
|
+
rightDelay.delayTime.value = CENTER_S;
|
|
1634
|
+
lfo.type = "triangle";
|
|
1531
1635
|
lfo.frequency.value = module.rate;
|
|
1532
|
-
lfoGainL.gain.value = module.depth *
|
|
1533
|
-
lfoGainR.gain.value = -module.depth *
|
|
1636
|
+
lfoGainL.gain.value = module.depth * SWING_S2;
|
|
1637
|
+
lfoGainR.gain.value = -module.depth * SWING_S2;
|
|
1534
1638
|
lfo.connect(lfoGainL);
|
|
1535
1639
|
lfo.connect(lfoGainR);
|
|
1536
1640
|
lfoGainL.connect(leftDelay.delayTime);
|
|
1537
1641
|
lfoGainR.connect(rightDelay.delayTime);
|
|
1538
1642
|
lfo.start();
|
|
1539
1643
|
input.connect(splitter);
|
|
1644
|
+
splitter.connect(aSum, 0);
|
|
1645
|
+
splitter.connect(bSum, 1);
|
|
1540
1646
|
splitter.connect(leftDelay, 0);
|
|
1541
1647
|
splitter.connect(rightDelay, 1);
|
|
1542
|
-
leftDelay.connect(
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
lrGain.connect(merger, 0, 1);
|
|
1549
|
-
|
|
1648
|
+
leftDelay.connect(diff);
|
|
1649
|
+
rightDelay.connect(invB).connect(diff);
|
|
1650
|
+
diff.connect(hp1).connect(hp2).connect(side);
|
|
1651
|
+
side.connect(aSum);
|
|
1652
|
+
side.connect(sideInv).connect(bSum);
|
|
1653
|
+
aSum.connect(llGain).connect(merger, 0, 0);
|
|
1654
|
+
aSum.connect(lrGain).connect(merger, 0, 1);
|
|
1655
|
+
bSum.connect(rlGain).connect(merger, 0, 0);
|
|
1656
|
+
bSum.connect(rrGain).connect(merger, 0, 1);
|
|
1550
1657
|
merger.connect(output);
|
|
1551
|
-
return { input, output, splitter, merger, leftDelay, rightDelay, lfo, lfoGainL, lfoGainR, llGain, rrGain, lrGain, rlGain };
|
|
1658
|
+
return { input, output, splitter, merger, leftDelay, rightDelay, lfo, lfoGainL, lfoGainR, invB, diff, hp1, hp2, side, sideInv, aSum, bSum, llGain, rrGain, lrGain, rlGain };
|
|
1552
1659
|
},
|
|
1553
1660
|
updateParam(nodes, _m, param, value) {
|
|
1554
|
-
if (param === "width")
|
|
1555
|
-
|
|
1556
|
-
nodes.llGain.gain.value = (1 + w) / 2;
|
|
1557
|
-
nodes.rrGain.gain.value = (1 + w) / 2;
|
|
1558
|
-
nodes.rlGain.gain.value = (1 - w) / 2;
|
|
1559
|
-
nodes.lrGain.gain.value = (1 - w) / 2;
|
|
1560
|
-
} else if (param === "rate") nodes.lfo.frequency.value = value;
|
|
1661
|
+
if (param === "width") setWidth(nodes, value);
|
|
1662
|
+
else if (param === "rate") nodes.lfo.frequency.value = value;
|
|
1561
1663
|
else if (param === "depth") {
|
|
1562
|
-
nodes.lfoGainL.gain.value = value *
|
|
1563
|
-
nodes.lfoGainR.gain.value = -value *
|
|
1664
|
+
nodes.lfoGainL.gain.value = value * SWING_S2;
|
|
1665
|
+
nodes.lfoGainR.gain.value = -value * SWING_S2;
|
|
1564
1666
|
}
|
|
1565
1667
|
},
|
|
1566
1668
|
dispose(nodes) {
|
|
@@ -1632,12 +1734,10 @@ var distortionDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1632
1734
|
const output = ctx.createGain();
|
|
1633
1735
|
const dryGain = ctx.createGain();
|
|
1634
1736
|
const wetGain = ctx.createGain();
|
|
1635
|
-
const waveshaper = ctx.
|
|
1737
|
+
const waveshaper = createShaperNode(ctx, makeDistortionCurve(module.distortionType, module.drive));
|
|
1636
1738
|
const makeup = ctx.createGain();
|
|
1637
1739
|
const dcBlock = ctx.createBiquadFilter();
|
|
1638
1740
|
const toneFilter = ctx.createBiquadFilter();
|
|
1639
|
-
waveshaper.curve = makeDistortionCurve(module.distortionType, module.drive);
|
|
1640
|
-
waveshaper.oversample = "4x";
|
|
1641
1741
|
makeup.gain.value = computeMakeup(module.distortionType, module.drive);
|
|
1642
1742
|
dcBlock.type = "highpass";
|
|
1643
1743
|
dcBlock.frequency.value = 10;
|
|
@@ -1646,9 +1746,9 @@ var distortionDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1646
1746
|
toneFilter.frequency.value = module.frequency;
|
|
1647
1747
|
toneFilter.Q.value = 0.707;
|
|
1648
1748
|
const _mix = createMix(ctx, dryGain, wetGain, module.mix, "linear");
|
|
1649
|
-
input.connect(dryGain);
|
|
1650
1749
|
input.connect(waveshaper);
|
|
1651
|
-
waveshaper.connect(
|
|
1750
|
+
waveshaper.connect(dryGain, 1);
|
|
1751
|
+
waveshaper.connect(makeup, 0);
|
|
1652
1752
|
makeup.connect(dcBlock);
|
|
1653
1753
|
dcBlock.connect(toneFilter);
|
|
1654
1754
|
toneFilter.connect(wetGain);
|
|
@@ -1658,7 +1758,7 @@ var distortionDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1658
1758
|
},
|
|
1659
1759
|
updateParam(nodes, module, param, value) {
|
|
1660
1760
|
if (param === "drive" || param === "distortionType") {
|
|
1661
|
-
nodes.waveshaper.curve
|
|
1761
|
+
nodes.waveshaper.port.postMessage({ curve: makeDistortionCurve(module.distortionType, module.drive) });
|
|
1662
1762
|
nodes.makeup.gain.value = computeMakeup(module.distortionType, module.drive);
|
|
1663
1763
|
}
|
|
1664
1764
|
if (param === "frequency") {
|
|
@@ -1671,7 +1771,11 @@ var distortionDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1671
1771
|
});
|
|
1672
1772
|
|
|
1673
1773
|
// src/lib-runtime/generated/modules/distortion.wrapper.ts
|
|
1674
|
-
var Distortion = /* @__PURE__ */ defineModule(distortionDescriptor
|
|
1774
|
+
var Distortion = /* @__PURE__ */ defineModule(distortionDescriptor, {
|
|
1775
|
+
worklets: {
|
|
1776
|
+
"shaper": shaper_default
|
|
1777
|
+
}
|
|
1778
|
+
});
|
|
1675
1779
|
|
|
1676
1780
|
// src/lib-runtime/generated/modules/ducker.tsx
|
|
1677
1781
|
var params11 = {
|
|
@@ -1973,22 +2077,21 @@ var exciterDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1973
2077
|
const dryGain = ctx.createGain();
|
|
1974
2078
|
const wetGain = ctx.createGain();
|
|
1975
2079
|
const highpass = ctx.createBiquadFilter();
|
|
1976
|
-
const saturation = ctx.
|
|
2080
|
+
const saturation = createShaperNode(ctx, makeExciterCurve(module.drive));
|
|
1977
2081
|
const highshelf = ctx.createBiquadFilter();
|
|
1978
2082
|
highpass.type = "highpass";
|
|
1979
2083
|
highpass.frequency.value = module.frequency;
|
|
1980
2084
|
highpass.Q.value = 0.7;
|
|
1981
|
-
saturation.curve = makeExciterCurve(module.drive);
|
|
1982
|
-
saturation.oversample = "2x";
|
|
1983
2085
|
highshelf.type = "highshelf";
|
|
1984
2086
|
highshelf.frequency.value = module.frequency;
|
|
1985
2087
|
highshelf.gain.value = 6 + module.drive * 6;
|
|
1986
2088
|
dryGain.gain.value = 1;
|
|
1987
2089
|
wetGain.gain.value = module.mix;
|
|
1988
|
-
input.connect(
|
|
2090
|
+
input.connect(saturation, 0, 1);
|
|
2091
|
+
saturation.connect(dryGain, 1);
|
|
1989
2092
|
input.connect(highpass);
|
|
1990
|
-
highpass.connect(saturation);
|
|
1991
|
-
saturation.connect(highshelf);
|
|
2093
|
+
highpass.connect(saturation, 0, 0);
|
|
2094
|
+
saturation.connect(highshelf, 0);
|
|
1992
2095
|
highshelf.connect(wetGain);
|
|
1993
2096
|
dryGain.connect(output);
|
|
1994
2097
|
wetGain.connect(output);
|
|
@@ -1996,7 +2099,7 @@ var exciterDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
1996
2099
|
},
|
|
1997
2100
|
updateParam(nodes, _m, param, value) {
|
|
1998
2101
|
if (param === "drive") {
|
|
1999
|
-
nodes.saturation.curve
|
|
2102
|
+
nodes.saturation.port.postMessage({ curve: makeExciterCurve(value) });
|
|
2000
2103
|
nodes.highshelf.gain.value = 6 + value * 6;
|
|
2001
2104
|
} else if (param === "frequency") {
|
|
2002
2105
|
nodes.highpass.frequency.value = value;
|
|
@@ -2008,7 +2111,11 @@ var exciterDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2008
2111
|
});
|
|
2009
2112
|
|
|
2010
2113
|
// src/lib-runtime/generated/modules/exciter.wrapper.ts
|
|
2011
|
-
var Exciter = /* @__PURE__ */ defineModule(exciterDescriptor
|
|
2114
|
+
var Exciter = /* @__PURE__ */ defineModule(exciterDescriptor, {
|
|
2115
|
+
worklets: {
|
|
2116
|
+
"shaper": shaper_default
|
|
2117
|
+
}
|
|
2118
|
+
});
|
|
2012
2119
|
|
|
2013
2120
|
// src/lib-runtime/generated/modules/flanger.tsx
|
|
2014
2121
|
var params16 = {
|
|
@@ -2076,7 +2183,7 @@ var Flanger = /* @__PURE__ */ defineModule(flangerDescriptor, {
|
|
|
2076
2183
|
// src/lib-runtime/generated/modules/formant.tsx
|
|
2077
2184
|
var params17 = {
|
|
2078
2185
|
morph: { unit: "factor", default: 0, min: 0, max: 5 },
|
|
2079
|
-
resonance: { unit: "factor", default: 6, min: 1, max: 20, scale: "sqrt" },
|
|
2186
|
+
resonance: { node: "formantWorklet", field: "resonance", unit: "factor", default: 6, min: 1, max: 20, scale: "sqrt" },
|
|
2080
2187
|
mix: { unit: "factor", default: 1, min: 0, max: 1 }
|
|
2081
2188
|
};
|
|
2082
2189
|
var formantDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
@@ -2095,75 +2202,54 @@ var formantDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2095
2202
|
const output = ctx.createGain();
|
|
2096
2203
|
const dryGain = ctx.createGain();
|
|
2097
2204
|
const wetGain = ctx.createGain();
|
|
2098
|
-
const
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2205
|
+
const bands = [0, 1, 2, 3, 4].map(() => {
|
|
2206
|
+
const f = ctx.createBiquadFilter();
|
|
2207
|
+
f.type = "bandpass";
|
|
2208
|
+
f.frequency.value = 0;
|
|
2209
|
+
f.Q.value = 0;
|
|
2210
|
+
return f;
|
|
2211
|
+
});
|
|
2104
2212
|
const formantWorklet = createFormantNode(ctx);
|
|
2105
|
-
|
|
2213
|
+
const wp = formantWorklet.parameters;
|
|
2214
|
+
wp.get("baseMorph").value = module.morph;
|
|
2215
|
+
wp.get("resonance").value = module.resonance;
|
|
2106
2216
|
const vowelCV = ctx.createGain();
|
|
2107
2217
|
vowelCV.gain.value = 1;
|
|
2108
2218
|
vowelCV.connect(formantWorklet);
|
|
2109
|
-
const splitter = ctx.createChannelSplitter(
|
|
2219
|
+
const splitter = ctx.createChannelSplitter(11);
|
|
2110
2220
|
formantWorklet.connect(splitter);
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
f2.Q.value = module.resonance * 0.4;
|
|
2128
|
-
f3.Q.value = module.resonance * 0.3;
|
|
2129
|
-
f4.Q.value = module.resonance * 0.25;
|
|
2130
|
-
f5.Q.value = module.resonance * 0.2;
|
|
2221
|
+
bands.forEach((f, k) => {
|
|
2222
|
+
splitter.connect(f.frequency, k);
|
|
2223
|
+
splitter.connect(f.Q, 5 + k);
|
|
2224
|
+
});
|
|
2225
|
+
const BAND_GAIN = [1, -1, 1, -0.5, 0.35];
|
|
2226
|
+
const bandGains = bands.map((f, k) => {
|
|
2227
|
+
const g = ctx.createGain();
|
|
2228
|
+
g.gain.value = BAND_GAIN[k];
|
|
2229
|
+
input.connect(f);
|
|
2230
|
+
f.connect(g);
|
|
2231
|
+
return g;
|
|
2232
|
+
});
|
|
2233
|
+
const formantMix = ctx.createGain();
|
|
2234
|
+
formantMix.gain.value = 0;
|
|
2235
|
+
splitter.connect(formantMix.gain, 10);
|
|
2236
|
+
bandGains.forEach((g) => g.connect(formantMix));
|
|
2131
2237
|
dryGain.gain.value = 1 - module.mix;
|
|
2132
2238
|
wetGain.gain.value = module.mix;
|
|
2133
|
-
formantMix.gain.value = 2;
|
|
2134
|
-
const f4Gain = ctx.createGain();
|
|
2135
|
-
const f5Gain = ctx.createGain();
|
|
2136
|
-
f4Gain.gain.value = 0.5;
|
|
2137
|
-
f5Gain.gain.value = 0.35;
|
|
2138
2239
|
input.connect(dryGain);
|
|
2139
|
-
input.connect(f1);
|
|
2140
|
-
input.connect(f2);
|
|
2141
|
-
input.connect(f3);
|
|
2142
|
-
input.connect(f4);
|
|
2143
|
-
input.connect(f5);
|
|
2144
|
-
f1.connect(formantMix);
|
|
2145
|
-
f2.connect(formantMix);
|
|
2146
|
-
f3.connect(formantMix);
|
|
2147
|
-
f4.connect(f4Gain);
|
|
2148
|
-
f5.connect(f5Gain);
|
|
2149
|
-
f4Gain.connect(formantMix);
|
|
2150
|
-
f5Gain.connect(formantMix);
|
|
2151
2240
|
formantMix.connect(wetGain);
|
|
2152
2241
|
dryGain.connect(output);
|
|
2153
2242
|
wetGain.connect(output);
|
|
2243
|
+
const [f1, f2, f3, f4, f5] = bands;
|
|
2154
2244
|
const _alive = createKeepAlive(ctx, f1, f2, f3, f4, f5);
|
|
2155
|
-
return { input, output, vowelCV, f1, f2, f3, f4, f5,
|
|
2245
|
+
return { input, output, vowelCV, f1, f2, f3, f4, f5, formantMix, dryGain, wetGain, formantWorklet, _alive };
|
|
2156
2246
|
},
|
|
2157
2247
|
updateParam(nodes, _module, param, value) {
|
|
2248
|
+
const wp = nodes.formantWorklet.parameters;
|
|
2158
2249
|
if (param === "morph") {
|
|
2159
|
-
|
|
2250
|
+
wp.get("baseMorph").value = value;
|
|
2160
2251
|
} else if (param === "resonance") {
|
|
2161
|
-
|
|
2162
|
-
nodes.f1.Q.value = r * 0.5;
|
|
2163
|
-
nodes.f2.Q.value = r * 0.4;
|
|
2164
|
-
nodes.f3.Q.value = r * 0.3;
|
|
2165
|
-
nodes.f4.Q.value = r * 0.25;
|
|
2166
|
-
nodes.f5.Q.value = r * 0.2;
|
|
2252
|
+
wp.get("resonance").value = value;
|
|
2167
2253
|
} else if (param === "mix") {
|
|
2168
2254
|
nodes.dryGain.gain.value = 1 - value;
|
|
2169
2255
|
nodes.wetGain.gain.value = value;
|
|
@@ -2230,35 +2316,22 @@ var FrequencyShifter = /* @__PURE__ */ defineModule(freqShifterDescriptor, {
|
|
|
2230
2316
|
|
|
2231
2317
|
// src/lib-runtime/generated/modules/gate.tsx
|
|
2232
2318
|
var params19 = {
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2319
|
+
threshold: { node: "gate", field: "threshold", unit: "dB", default: -40, min: -60, max: 0 },
|
|
2320
|
+
range: { node: "gate", field: "range", unit: "factor", default: 0.8, min: 0, max: 1 },
|
|
2321
|
+
// ATK/REL shape the VCA gain's own attack/release ramp once the (fixed,
|
|
2322
|
+
// fast) detector has decided open/closed — same separation as a real
|
|
2323
|
+
// hardware gate (e.g. Drawmer DS201). See src/worklets/gate.ts.
|
|
2324
|
+
attack: { node: "gate", field: "attack", unit: "s", default: 5e-3, min: 1e-3, max: 0.05, scale: "log" },
|
|
2325
|
+
release: { node: "gate", field: "release", unit: "s", default: 0.1, min: 0.01, max: 0.5, scale: "log" },
|
|
2326
|
+
// A switch, not jack sensing (see src/worklets/gate.ts).
|
|
2327
|
+
keySource: { kind: "enum", options: ["internal", "external"], default: "internal" }
|
|
2239
2328
|
};
|
|
2240
|
-
function makeGateCurve(threshold, range) {
|
|
2241
|
-
const threshLinear = Math.pow(10, threshold / 20);
|
|
2242
|
-
const kneeLow = Math.pow(10, (threshold - 2) / 20);
|
|
2243
|
-
const closed = 1 - range;
|
|
2244
|
-
const gsLen = 32768;
|
|
2245
|
-
const gsCurve = new Float32Array(gsLen);
|
|
2246
|
-
for (let i = 0; i < gsLen; i++) {
|
|
2247
|
-
const x = i / (gsLen - 1) * 2 - 1;
|
|
2248
|
-
const env = Math.max(0, x);
|
|
2249
|
-
let g;
|
|
2250
|
-
if (env >= threshLinear) g = 1;
|
|
2251
|
-
else if (env <= kneeLow) g = closed;
|
|
2252
|
-
else g = closed + (1 - closed) * ((env - kneeLow) / (threshLinear - kneeLow));
|
|
2253
|
-
gsCurve[i] = g;
|
|
2254
|
-
}
|
|
2255
|
-
return gsCurve;
|
|
2256
|
-
}
|
|
2257
2329
|
var gateDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
2258
2330
|
type: "gate",
|
|
2259
2331
|
params: params19,
|
|
2260
2332
|
ports: {
|
|
2261
2333
|
"in": { type: "input", signal: "audio", node: "input" },
|
|
2334
|
+
"key": { type: "input", signal: "audio", node: "_keyIn" },
|
|
2262
2335
|
"out": { type: "output", signal: "audio", node: "output" }
|
|
2263
2336
|
},
|
|
2264
2337
|
createModule(id, position) {
|
|
@@ -2267,37 +2340,33 @@ var gateDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2267
2340
|
createNodes(ctx, module) {
|
|
2268
2341
|
const input = ctx.createGain();
|
|
2269
2342
|
const output = ctx.createGain();
|
|
2270
|
-
const
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
return { input, output,
|
|
2343
|
+
const gate = createGateNode(ctx);
|
|
2344
|
+
gate.parameters.get("threshold").value = module.threshold;
|
|
2345
|
+
gate.parameters.get("range").value = module.range;
|
|
2346
|
+
gate.parameters.get("attack").value = module.attack;
|
|
2347
|
+
gate.parameters.get("release").value = module.release;
|
|
2348
|
+
gate.parameters.get("keyExt").value = module.keySource === "external" ? 1 : 0;
|
|
2349
|
+
const _keyIn = ctx.createGain();
|
|
2350
|
+
_keyIn.channelCount = 2;
|
|
2351
|
+
_keyIn.channelCountMode = "clamped-max";
|
|
2352
|
+
input.connect(gate);
|
|
2353
|
+
_keyIn.connect(gate, 0, 1);
|
|
2354
|
+
gate.connect(output);
|
|
2355
|
+
return { input, output, gate, _keyIn };
|
|
2283
2356
|
},
|
|
2284
2357
|
updateParam(nodes, module, param, value) {
|
|
2285
|
-
if (param === "
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
nodes.gateShaper.curve = makeGateCurve(thresh, range);
|
|
2289
|
-
} else if (param === "attack") {
|
|
2290
|
-
nodes.envFollower.parameters.get("attack").value = value;
|
|
2291
|
-
} else if (param === "release") {
|
|
2292
|
-
nodes.envFollower.parameters.get("release").value = value;
|
|
2358
|
+
if (param === "keySource") {
|
|
2359
|
+
nodes.gate.parameters.get("keyExt").value = value === "external" ? 1 : 0;
|
|
2360
|
+
return;
|
|
2293
2361
|
}
|
|
2362
|
+
nodes.gate.parameters.get(param).value = value;
|
|
2294
2363
|
}
|
|
2295
2364
|
});
|
|
2296
2365
|
|
|
2297
2366
|
// src/lib-runtime/generated/modules/gate.wrapper.ts
|
|
2298
2367
|
var Gate = /* @__PURE__ */ defineModule(gateDescriptor, {
|
|
2299
2368
|
worklets: {
|
|
2300
|
-
"
|
|
2369
|
+
"gate": gate_default
|
|
2301
2370
|
}
|
|
2302
2371
|
});
|
|
2303
2372
|
|
|
@@ -2422,7 +2491,7 @@ var HaasWidener = /* @__PURE__ */ defineModule(haasDescriptor);
|
|
|
2422
2491
|
var params22 = {
|
|
2423
2492
|
rate: { node: "lfo", field: "frequency", unit: "Hz", default: 4, min: 1, max: 10 },
|
|
2424
2493
|
depth: { unit: "factor", default: 0.7, min: 0, max: 1 },
|
|
2425
|
-
crossover: { node: "
|
|
2494
|
+
crossover: { node: "_xover", field: "offset", unit: "Hz", default: 800, min: 200, max: 2e3 }
|
|
2426
2495
|
};
|
|
2427
2496
|
var harmonicTremDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
2428
2497
|
type: "harmonic-trem",
|
|
@@ -2431,7 +2500,7 @@ var harmonicTremDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2431
2500
|
"in": { type: "input", signal: "audio", node: "input" },
|
|
2432
2501
|
"out": { type: "output", signal: "audio", node: "output" },
|
|
2433
2502
|
"modRate": { type: "modulation", signal: "modulation", node: "lfo", field: "frequency" },
|
|
2434
|
-
"modCrossover": { type: "modulation", signal: "modulation", node: "
|
|
2503
|
+
"modCrossover": { type: "modulation", signal: "modulation", node: "_xover", field: "offset" }
|
|
2435
2504
|
},
|
|
2436
2505
|
createModule(id, position) {
|
|
2437
2506
|
return { id, type: "harmonic-trem", position, ...paramDefaults(params22) };
|
|
@@ -2440,8 +2509,9 @@ var harmonicTremDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2440
2509
|
const input = ctx.createGain();
|
|
2441
2510
|
const output = ctx.createGain();
|
|
2442
2511
|
const lowpass = ctx.createBiquadFilter();
|
|
2443
|
-
const
|
|
2444
|
-
const
|
|
2512
|
+
const highpass = ctx.createBiquadFilter();
|
|
2513
|
+
const hpInvert = ctx.createGain();
|
|
2514
|
+
const _xover = ctx.createConstantSource();
|
|
2445
2515
|
const lowGain = ctx.createGain();
|
|
2446
2516
|
const highGain = ctx.createGain();
|
|
2447
2517
|
const lfo = ctx.createOscillator();
|
|
@@ -2449,10 +2519,14 @@ var harmonicTremDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2449
2519
|
const lfoGainHigh = ctx.createGain();
|
|
2450
2520
|
const lfoInvert = ctx.createGain();
|
|
2451
2521
|
lowpass.type = "lowpass";
|
|
2452
|
-
|
|
2453
|
-
lowpass
|
|
2454
|
-
|
|
2455
|
-
|
|
2522
|
+
highpass.type = "highpass";
|
|
2523
|
+
for (const f of [lowpass, highpass]) {
|
|
2524
|
+
f.Q.value = -6.0206;
|
|
2525
|
+
f.frequency.value = 0;
|
|
2526
|
+
_xover.connect(f.frequency);
|
|
2527
|
+
}
|
|
2528
|
+
_xover.offset.value = module.crossover;
|
|
2529
|
+
hpInvert.gain.value = -1;
|
|
2456
2530
|
lfo.type = "sine";
|
|
2457
2531
|
lfo.frequency.value = module.rate;
|
|
2458
2532
|
lfoGainLow.gain.value = module.depth * 0.5;
|
|
@@ -2461,20 +2535,20 @@ var harmonicTremDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2461
2535
|
lowGain.gain.value = 1;
|
|
2462
2536
|
highGain.gain.value = 1;
|
|
2463
2537
|
input.connect(lowpass);
|
|
2464
|
-
input.connect(
|
|
2465
|
-
|
|
2466
|
-
lpInvert.connect(highBand);
|
|
2538
|
+
input.connect(highpass);
|
|
2539
|
+
highpass.connect(hpInvert);
|
|
2467
2540
|
lfo.connect(lfoGainLow);
|
|
2468
2541
|
lfo.connect(lfoInvert);
|
|
2469
2542
|
lfoInvert.connect(lfoGainHigh);
|
|
2470
2543
|
lfoGainLow.connect(lowGain.gain);
|
|
2471
2544
|
lfoGainHigh.connect(highGain.gain);
|
|
2472
2545
|
lowpass.connect(lowGain);
|
|
2473
|
-
|
|
2546
|
+
hpInvert.connect(highGain);
|
|
2474
2547
|
lowGain.connect(output);
|
|
2475
2548
|
highGain.connect(output);
|
|
2476
2549
|
lfo.start();
|
|
2477
|
-
|
|
2550
|
+
_xover.start();
|
|
2551
|
+
return { input, output, lfo, lfoGainLow, lfoGainHigh, lowpass, highpass, hpInvert, _xover };
|
|
2478
2552
|
},
|
|
2479
2553
|
updateParam(nodes, _m, param, value) {
|
|
2480
2554
|
if (param === "rate") nodes.lfo.frequency.value = value;
|
|
@@ -2482,10 +2556,11 @@ var harmonicTremDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2482
2556
|
nodes.lfoGainLow.gain.value = value * 0.5;
|
|
2483
2557
|
nodes.lfoGainHigh.gain.value = value * 0.5;
|
|
2484
2558
|
} else if (param === "crossover") {
|
|
2485
|
-
nodes.
|
|
2559
|
+
nodes._xover.offset.value = value;
|
|
2486
2560
|
}
|
|
2487
2561
|
},
|
|
2488
2562
|
dispose(nodes) {
|
|
2563
|
+
nodes._xover.stop();
|
|
2489
2564
|
nodes.lfo.stop();
|
|
2490
2565
|
}
|
|
2491
2566
|
});
|
|
@@ -2623,21 +2698,27 @@ var Lfo = /* @__PURE__ */ defineModule(lfoDescriptor, {
|
|
|
2623
2698
|
});
|
|
2624
2699
|
|
|
2625
2700
|
// src/lib-runtime/generated/modules/lo-fi.tsx
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2701
|
+
var DRIVE_BIAS = 0.3;
|
|
2702
|
+
var INPUT_SPAN = 16;
|
|
2703
|
+
var CURVE_LEN2 = 32769;
|
|
2704
|
+
var WOBBLE_MAX_S = 2e-3;
|
|
2705
|
+
var driveK = (drive) => 0.125 * Math.pow(128, Math.max(0, Math.min(1, drive)));
|
|
2706
|
+
function loFiCurve(drive) {
|
|
2707
|
+
const k = driveK(drive);
|
|
2708
|
+
const t0 = Math.tanh(DRIVE_BIAS);
|
|
2709
|
+
const slope0 = 1 - t0 * t0;
|
|
2710
|
+
const c = new Float32Array(CURVE_LEN2);
|
|
2711
|
+
for (let i = 0; i < CURVE_LEN2; i++) {
|
|
2712
|
+
const v = i * 2 / (CURVE_LEN2 - 1) - 1;
|
|
2713
|
+
c[i] = (Math.tanh(k * INPUT_SPAN * v + DRIVE_BIAS) - t0) / (k * slope0);
|
|
2633
2714
|
}
|
|
2634
|
-
return
|
|
2715
|
+
return c;
|
|
2635
2716
|
}
|
|
2636
2717
|
var params25 = {
|
|
2637
2718
|
drive: { unit: "factor", default: 0.3, min: 0, max: 1 },
|
|
2638
2719
|
cutoff: { node: "lowpass", field: "frequency", unit: "Hz", default: 4e3, min: 500, max: 8e3 },
|
|
2639
|
-
noise: { unit: "factor", default: 0.2, min: 0, max: 1 },
|
|
2640
|
-
wobble: { unit: "factor", default: 0.1, min: 0, max: 1 }
|
|
2720
|
+
noise: { node: "noiseGain", field: "gain", unit: "factor", default: 0.2, min: 0, max: 1 },
|
|
2721
|
+
wobble: { node: "wobbleAmt", field: "offset", unit: "factor", default: 0.1, min: 0, max: 1 }
|
|
2641
2722
|
};
|
|
2642
2723
|
var loFiDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
2643
2724
|
type: "lo-fi",
|
|
@@ -2653,73 +2734,78 @@ var loFiDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
2653
2734
|
createNodes(ctx, module) {
|
|
2654
2735
|
const input = ctx.createGain();
|
|
2655
2736
|
const output = ctx.createGain();
|
|
2656
|
-
const
|
|
2737
|
+
const preGain = ctx.createGain();
|
|
2738
|
+
preGain.gain.value = 1 / INPUT_SPAN;
|
|
2739
|
+
const saturation = createShaperNode(ctx, loFiCurve(module.drive), { dry: false });
|
|
2740
|
+
const dcBlock = ctx.createBiquadFilter();
|
|
2741
|
+
dcBlock.type = "highpass";
|
|
2742
|
+
dcBlock.frequency.value = 10;
|
|
2743
|
+
dcBlock.Q.value = Math.SQRT1_2;
|
|
2657
2744
|
const lowpass = ctx.createBiquadFilter();
|
|
2658
|
-
const noiseGain = ctx.createGain();
|
|
2659
|
-
const wobbleLfo = ctx.createOscillator();
|
|
2660
|
-
const wobbleGain = ctx.createGain();
|
|
2661
|
-
saturation.curve = makeLoFiSaturationCurve(module.drive);
|
|
2662
|
-
saturation.oversample = "2x";
|
|
2663
2745
|
lowpass.type = "lowpass";
|
|
2664
2746
|
lowpass.frequency.value = module.cutoff;
|
|
2665
2747
|
lowpass.Q.value = 0.7;
|
|
2666
|
-
const
|
|
2667
|
-
|
|
2668
|
-
const
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
for (let i = 0; i < bufferSize; i++) {
|
|
2672
|
-
const white = rand();
|
|
2673
|
-
b0 = 0.99765 * b0 + white * 0.099046;
|
|
2674
|
-
b1 = 0.963 * b1 + white * 0.2965164;
|
|
2675
|
-
b2 = 0.57 * b2 + white * 1.0526913;
|
|
2676
|
-
data[i] = (b0 + b1 + b2) * 0.1;
|
|
2677
|
-
}
|
|
2678
|
-
const noiseSrc = ctx.createBufferSource();
|
|
2679
|
-
noiseSrc.buffer = noiseBuffer2;
|
|
2680
|
-
noiseSrc.loop = true;
|
|
2681
|
-
noiseGain.gain.value = module.noise * 0.05;
|
|
2682
|
-
noiseSrc.connect(noiseGain);
|
|
2683
|
-
noiseSrc.start();
|
|
2684
|
-
const wobbleDelay = ctx.createDelay(0.05);
|
|
2685
|
-
wobbleDelay.delayTime.value = 0.01;
|
|
2748
|
+
const wobbleAmt = ctx.createConstantSource();
|
|
2749
|
+
wobbleAmt.offset.value = module.wobble;
|
|
2750
|
+
const wobbleScale = ctx.createGain();
|
|
2751
|
+
wobbleScale.gain.value = WOBBLE_MAX_S;
|
|
2752
|
+
const wobbleLfo = ctx.createOscillator();
|
|
2686
2753
|
wobbleLfo.type = "sine";
|
|
2687
2754
|
wobbleLfo.frequency.value = 0.73;
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2755
|
+
const wobbleDepth = ctx.createGain();
|
|
2756
|
+
wobbleDepth.gain.value = 0;
|
|
2757
|
+
const wobbleDelay = ctx.createDelay(0.05);
|
|
2758
|
+
wobbleDelay.delayTime.value = 0;
|
|
2759
|
+
wobbleAmt.connect(wobbleScale);
|
|
2760
|
+
wobbleScale.connect(wobbleDelay.delayTime);
|
|
2761
|
+
wobbleScale.connect(wobbleDepth.gain);
|
|
2762
|
+
wobbleLfo.connect(wobbleDepth);
|
|
2763
|
+
wobbleDepth.connect(wobbleDelay.delayTime);
|
|
2764
|
+
wobbleAmt.start();
|
|
2691
2765
|
wobbleLfo.start();
|
|
2692
|
-
|
|
2693
|
-
|
|
2766
|
+
const noiseSrc = createVinylNoiseNode(ctx, NOISE_SEEDS.loFiCrackle);
|
|
2767
|
+
const noiseGain = ctx.createGain();
|
|
2768
|
+
noiseGain.gain.value = module.noise;
|
|
2769
|
+
noiseSrc.connect(noiseGain);
|
|
2770
|
+
input.connect(preGain);
|
|
2771
|
+
preGain.connect(saturation);
|
|
2772
|
+
saturation.connect(dcBlock, 0);
|
|
2773
|
+
dcBlock.connect(lowpass);
|
|
2694
2774
|
lowpass.connect(wobbleDelay);
|
|
2695
2775
|
wobbleDelay.connect(output);
|
|
2696
2776
|
noiseGain.connect(output);
|
|
2697
|
-
return { input, output, saturation,
|
|
2777
|
+
return { input, output, preGain, saturation, dcBlock, lowpass, wobbleAmt, wobbleScale, wobbleLfo, wobbleDepth, wobbleDelay, noiseSrc, noiseGain };
|
|
2698
2778
|
},
|
|
2699
2779
|
updateParam(nodes, _m, param, value) {
|
|
2700
2780
|
if (param === "drive") {
|
|
2701
|
-
nodes.saturation.curve
|
|
2781
|
+
nodes.saturation.port.postMessage({ curve: loFiCurve(value) });
|
|
2702
2782
|
} else if (param === "cutoff") {
|
|
2703
2783
|
nodes.lowpass.frequency.value = value;
|
|
2704
2784
|
} else if (param === "noise") {
|
|
2705
|
-
nodes.noiseGain.gain.value = value
|
|
2785
|
+
nodes.noiseGain.gain.value = value;
|
|
2706
2786
|
} else if (param === "wobble") {
|
|
2707
|
-
nodes.
|
|
2787
|
+
nodes.wobbleAmt.offset.value = value;
|
|
2708
2788
|
}
|
|
2709
2789
|
},
|
|
2710
2790
|
dispose(nodes) {
|
|
2711
2791
|
nodes.wobbleLfo.stop();
|
|
2712
|
-
nodes.
|
|
2792
|
+
nodes.wobbleAmt.stop();
|
|
2713
2793
|
}
|
|
2714
2794
|
});
|
|
2715
2795
|
|
|
2716
2796
|
// src/lib-runtime/generated/modules/lo-fi.wrapper.ts
|
|
2717
|
-
var LoFi = /* @__PURE__ */ defineModule(loFiDescriptor
|
|
2797
|
+
var LoFi = /* @__PURE__ */ defineModule(loFiDescriptor, {
|
|
2798
|
+
worklets: {
|
|
2799
|
+
"shaper": shaper_default,
|
|
2800
|
+
"vinyl-noise": vinyl_noise_default
|
|
2801
|
+
}
|
|
2802
|
+
});
|
|
2718
2803
|
|
|
2719
2804
|
// src/lib-runtime/generated/modules/mid-side.tsx
|
|
2720
2805
|
var params26 = {
|
|
2721
2806
|
midGain: { node: "midGainNode", field: "gain", unit: "factor", default: 1, min: 0, max: 2 },
|
|
2722
|
-
sideGain: { node: "sideGainNode", field: "gain", unit: "factor", default: 1, min: 0, max: 2 }
|
|
2807
|
+
sideGain: { node: "sideGainNode", field: "gain", unit: "factor", default: 1, min: 0, max: 2 },
|
|
2808
|
+
width: { node: "widthNode", field: "gain", unit: "factor", default: 1, min: 0, max: 2 }
|
|
2723
2809
|
};
|
|
2724
2810
|
var midSideDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
2725
2811
|
type: "mid-side",
|
|
@@ -3162,9 +3248,58 @@ function dampingToQ(damping) {
|
|
|
3162
3248
|
const d = Math.min(1, Math.max(0, Number.isFinite(damping) ? damping : 0.5));
|
|
3163
3249
|
return MODAL_Q_MAX * Math.pow(MODAL_Q_MIN / MODAL_Q_MAX, d);
|
|
3164
3250
|
}
|
|
3251
|
+
function modeT60(q, hz2) {
|
|
3252
|
+
return T60_PER_Q_HZ * q / hz2;
|
|
3253
|
+
}
|
|
3165
3254
|
function modalMakeup(q) {
|
|
3166
3255
|
return Math.sqrt(Math.max(1, q));
|
|
3167
3256
|
}
|
|
3257
|
+
var MODAL_PARTIALS = 5;
|
|
3258
|
+
var MODAL_REF_NOTE = 57;
|
|
3259
|
+
function partialEnergySum(structure) {
|
|
3260
|
+
let s = 0;
|
|
3261
|
+
for (let n = 1; n <= MODAL_PARTIALS; n++) s += Math.pow(n, -(1 + structure));
|
|
3262
|
+
return s;
|
|
3263
|
+
}
|
|
3264
|
+
function modalPartialGain(n, q, structure) {
|
|
3265
|
+
return modalMakeup(q) * Math.pow(n, -(1 + structure)) * Math.sqrt(MODAL_PARTIALS / partialEnergySum(structure)) * modalOverlapGain(q, structure);
|
|
3266
|
+
}
|
|
3267
|
+
var OVERLAP_REF_HZ = 220;
|
|
3268
|
+
var OVERLAP_SR = 48e3;
|
|
3269
|
+
var overlapCache = /* @__PURE__ */ new Map();
|
|
3270
|
+
function modalOverlapGain(q, structure) {
|
|
3271
|
+
if (!(q < 40)) return 1;
|
|
3272
|
+
const key = `${q.toFixed(4)}:${structure.toFixed(4)}`;
|
|
3273
|
+
const hit = overlapCache.get(key);
|
|
3274
|
+
if (hit !== void 0) return hit;
|
|
3275
|
+
const n = Math.ceil(2 * modeT60(q, OVERLAP_REF_HZ) * OVERLAP_SR) + 64;
|
|
3276
|
+
const sum = new Float64Array(n);
|
|
3277
|
+
let incoherent = 0;
|
|
3278
|
+
for (let p = 1; p <= MODAL_PARTIALS; p++) {
|
|
3279
|
+
const f0 = Math.min(OVERLAP_SR * 0.45, OVERLAP_REF_HZ * Math.pow(p, 1 + structure));
|
|
3280
|
+
const g = Math.pow(p, -(1 + structure));
|
|
3281
|
+
const w0 = 2 * Math.PI * f0 / OVERLAP_SR;
|
|
3282
|
+
const alpha = Math.sin(w0) / (2 * q);
|
|
3283
|
+
const a0 = 1 + alpha;
|
|
3284
|
+
const b0 = alpha / a0, a1 = -2 * Math.cos(w0) / a0, a2 = (1 - alpha) / a0;
|
|
3285
|
+
let y2 = 0, y1 = 0;
|
|
3286
|
+
for (let i = 0; i < n; i++) {
|
|
3287
|
+
const x = i === 0 ? b0 : i === 2 ? -b0 : 0;
|
|
3288
|
+
const y = x - a1 * y1 - a2 * y2;
|
|
3289
|
+
y2 = y1;
|
|
3290
|
+
y1 = y;
|
|
3291
|
+
sum[i] += g * y;
|
|
3292
|
+
incoherent += g * g * y * y;
|
|
3293
|
+
}
|
|
3294
|
+
}
|
|
3295
|
+
let coherent = 0;
|
|
3296
|
+
for (let i = 0; i < n; i++) coherent += sum[i] * sum[i];
|
|
3297
|
+
const gain = coherent > 0 ? Math.sqrt(incoherent / coherent) : 1;
|
|
3298
|
+
if (overlapCache.size > 4096) overlapCache.clear();
|
|
3299
|
+
overlapCache.set(key, gain);
|
|
3300
|
+
return gain;
|
|
3301
|
+
}
|
|
3302
|
+
var MODAL_PITCH_GAIN_TRANSPOSE = 69 + 12 * (MODAL_REF_NOTE / 24 - Math.log2(440));
|
|
3168
3303
|
|
|
3169
3304
|
// src/lib-runtime/generated/modules/resonator.tsx
|
|
3170
3305
|
var params31 = {
|
|
@@ -3172,12 +3307,13 @@ var params31 = {
|
|
|
3172
3307
|
offset: { node: "_root", field: "offset", default: 57, min: -48, max: 108, unit: "semitone" },
|
|
3173
3308
|
structure: { unit: "factor", default: 0, min: 0, max: 1 },
|
|
3174
3309
|
damping: { unit: "factor", default: 0.5, min: 0, max: 1 },
|
|
3175
|
-
mix: { node: "_mix", field: "offset", unit: "factor", default:
|
|
3310
|
+
mix: { node: "_mix", field: "offset", unit: "factor", default: 1, min: 0, max: 1 }
|
|
3176
3311
|
};
|
|
3177
3312
|
function partialOffset(partial, structure) {
|
|
3178
3313
|
return 12 * (1 + structure) * Math.log2(partial);
|
|
3179
3314
|
}
|
|
3180
3315
|
var patchCount2 = /* @__PURE__ */ new WeakMap();
|
|
3316
|
+
var shape = /* @__PURE__ */ new WeakMap();
|
|
3181
3317
|
var resonatorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
3182
3318
|
type: "resonator",
|
|
3183
3319
|
params: params31,
|
|
@@ -3205,7 +3341,17 @@ var resonatorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3205
3341
|
const partialGains = [];
|
|
3206
3342
|
const voct = [];
|
|
3207
3343
|
const q = dampingToQ(module.damping);
|
|
3208
|
-
|
|
3344
|
+
shape.set(_pitch, { q, structure: module.structure });
|
|
3345
|
+
const _halfPitch = ctx.createGain();
|
|
3346
|
+
_halfPitch.gain.value = -0.5;
|
|
3347
|
+
_pitch.connect(_halfPitch);
|
|
3348
|
+
const _trackGain = createVoctFreqNode(ctx);
|
|
3349
|
+
_trackGain.parameters.get("transpose").value = MODAL_PITCH_GAIN_TRANSPOSE;
|
|
3350
|
+
_halfPitch.connect(_trackGain);
|
|
3351
|
+
const _track = ctx.createGain();
|
|
3352
|
+
_track.gain.value = 0;
|
|
3353
|
+
_trackGain.connect(_track.gain);
|
|
3354
|
+
_track.connect(wetGain);
|
|
3209
3355
|
for (let i = 1; i <= 5; i++) {
|
|
3210
3356
|
const v = createVoctFreqNode(ctx);
|
|
3211
3357
|
v.parameters.get("transpose").value = partialOffset(i, module.structure);
|
|
@@ -3219,9 +3365,9 @@ var resonatorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3219
3365
|
voct.push(v);
|
|
3220
3366
|
input.connect(filter);
|
|
3221
3367
|
const partialGain = ctx.createGain();
|
|
3222
|
-
partialGain.gain.value =
|
|
3368
|
+
partialGain.gain.value = modalPartialGain(i, q, module.structure);
|
|
3223
3369
|
filter.connect(partialGain);
|
|
3224
|
-
partialGain.connect(
|
|
3370
|
+
partialGain.connect(_track);
|
|
3225
3371
|
partialGains.push(partialGain);
|
|
3226
3372
|
}
|
|
3227
3373
|
const _alive = createKeepAlive(ctx, ...filters);
|
|
@@ -3238,6 +3384,9 @@ var resonatorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3238
3384
|
_root,
|
|
3239
3385
|
_pitch,
|
|
3240
3386
|
_alive,
|
|
3387
|
+
_halfPitch,
|
|
3388
|
+
_trackGain,
|
|
3389
|
+
_track,
|
|
3241
3390
|
v1: voct[0],
|
|
3242
3391
|
v2: voct[1],
|
|
3243
3392
|
v3: voct[2],
|
|
@@ -3263,19 +3412,20 @@ var resonatorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3263
3412
|
if (!patchCount2.get(nodes)) nodes._root.offset.value = value;
|
|
3264
3413
|
} else if (param === "transpose") {
|
|
3265
3414
|
if (patchCount2.get(nodes)) nodes._root.offset.value = value;
|
|
3266
|
-
} else if (param === "structure") {
|
|
3267
|
-
const
|
|
3268
|
-
|
|
3269
|
-
|
|
3415
|
+
} else if (param === "structure" || param === "damping") {
|
|
3416
|
+
const st = shape.get(nodes._pitch);
|
|
3417
|
+
if (param === "structure") {
|
|
3418
|
+
st.structure = value;
|
|
3419
|
+
const voct = [nodes.v1, nodes.v2, nodes.v3, nodes.v4, nodes.v5];
|
|
3420
|
+
for (let i = 1; i < 5; i++) {
|
|
3421
|
+
voct[i].parameters.get("transpose").value = partialOffset(i + 1, st.structure);
|
|
3422
|
+
}
|
|
3423
|
+
} else {
|
|
3424
|
+
st.q = dampingToQ(value);
|
|
3425
|
+
for (const f of filters) f.Q.value = st.q;
|
|
3270
3426
|
}
|
|
3271
|
-
} else if (param === "damping") {
|
|
3272
|
-
const q = dampingToQ(value);
|
|
3273
|
-
const makeup = modalMakeup(q);
|
|
3274
3427
|
const gains = [nodes.g1, nodes.g2, nodes.g3, nodes.g4, nodes.g5];
|
|
3275
|
-
for (let i = 0; i < 5; i++)
|
|
3276
|
-
filters[i].Q.value = q;
|
|
3277
|
-
gains[i].gain.value = makeup / Math.sqrt(i + 1);
|
|
3278
|
-
}
|
|
3428
|
+
for (let i = 0; i < 5; i++) gains[i].gain.value = modalPartialGain(i + 1, st.q, st.structure);
|
|
3279
3429
|
} else if (param === "mix") {
|
|
3280
3430
|
nodes._mix.offset.value = value;
|
|
3281
3431
|
}
|
|
@@ -3314,13 +3464,30 @@ var Resonator = /* @__PURE__ */ defineModule(resonatorDescriptor, {
|
|
|
3314
3464
|
});
|
|
3315
3465
|
|
|
3316
3466
|
// src/lib/dsp/fdnTank.ts
|
|
3317
|
-
var
|
|
3467
|
+
var LINE_MS = [
|
|
3468
|
+
32.479167,
|
|
3469
|
+
32.645833,
|
|
3470
|
+
39.354167,
|
|
3471
|
+
37.979167,
|
|
3472
|
+
44.854167,
|
|
3473
|
+
46.729167,
|
|
3474
|
+
54.854167,
|
|
3475
|
+
54.020833,
|
|
3476
|
+
64.354167,
|
|
3477
|
+
65.020833,
|
|
3478
|
+
77.770833,
|
|
3479
|
+
76.229167,
|
|
3480
|
+
90.770833,
|
|
3481
|
+
91.854167,
|
|
3482
|
+
108.520833,
|
|
3483
|
+
108.270833
|
|
3484
|
+
];
|
|
3318
3485
|
function tankEnergyGain500(rt60, size = 1) {
|
|
3319
3486
|
let g2 = 0;
|
|
3320
|
-
for (const ms2 of
|
|
3321
|
-
g2 /=
|
|
3487
|
+
for (const ms2 of LINE_MS) g2 += Math.pow(10, -6 * (ms2 / 1e3) * size / Math.max(rt60, 0.05));
|
|
3488
|
+
g2 /= LINE_MS.length;
|
|
3322
3489
|
const loss = 1 - g2;
|
|
3323
|
-
return Math.max(0.
|
|
3490
|
+
return Math.max(0.01, 1.32117 / loss - 1.32832 - 0.01158 * loss);
|
|
3324
3491
|
}
|
|
3325
3492
|
function createFdnTank(ctx, opts) {
|
|
3326
3493
|
const input = ctx.createGain();
|
|
@@ -3500,10 +3667,10 @@ var RingModulator = /* @__PURE__ */ defineModule(ringModDescriptor, {
|
|
|
3500
3667
|
|
|
3501
3668
|
// src/lib-runtime/generated/modules/rotary.tsx
|
|
3502
3669
|
var CROSSOVER_HZ = 800;
|
|
3503
|
-
var
|
|
3670
|
+
var BUTTERWORTH_Q_DB2 = -3.0103;
|
|
3504
3671
|
var DRUM_RATIO = 0.85;
|
|
3505
|
-
var HORN = { baseDelay: 3e-3, dopplerSec: 44e-5, ampBase: 0.
|
|
3506
|
-
var DRUM = { baseDelay: 3e-3, dopplerSec: 2e-4, ampBase: 0.
|
|
3672
|
+
var HORN = { baseDelay: 3e-3, dopplerSec: 44e-5, ampBase: 0.54, ampDepth: 0.46, phaseDeg: 0, tauUp: 0.35, tauDown: 0.55 };
|
|
3673
|
+
var DRUM = { baseDelay: 3e-3, dopplerSec: 2e-4, ampBase: 0.6, ampDepth: 0.4, phaseDeg: 90, tauUp: 1.5, tauDown: 1.7 };
|
|
3507
3674
|
var params34 = {
|
|
3508
3675
|
speed: { kind: "enum", options: ["slow", "fast"], default: "slow" },
|
|
3509
3676
|
slowRate: { unit: "Hz", default: 0.8, min: 0.5, max: 2 },
|
|
@@ -3536,7 +3703,7 @@ var rotaryDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3536
3703
|
const f = ctx.createBiquadFilter();
|
|
3537
3704
|
f.type = type;
|
|
3538
3705
|
f.frequency.value = CROSSOVER_HZ;
|
|
3539
|
-
f.Q.value =
|
|
3706
|
+
f.Q.value = BUTTERWORTH_Q_DB2;
|
|
3540
3707
|
return f;
|
|
3541
3708
|
};
|
|
3542
3709
|
const lp1 = biquad("lowpass"), lp2 = biquad("lowpass");
|
|
@@ -3629,22 +3796,24 @@ var Rotary = /* @__PURE__ */ defineModule(rotaryDescriptor);
|
|
|
3629
3796
|
|
|
3630
3797
|
// src/lib-runtime/generated/modules/saturator.tsx
|
|
3631
3798
|
var params35 = {
|
|
3632
|
-
//
|
|
3633
|
-
//
|
|
3799
|
+
// DRIVE reshapes the curve (hotter knee, output trimmed to match) — no
|
|
3800
|
+
// single AudioParam carries it: set-only.
|
|
3634
3801
|
drive: { unit: "factor", default: 0.5, min: 0, max: 1 },
|
|
3635
3802
|
// warmthFilter.gain = warmth * 6 — a scaled conversion, so no node/field.
|
|
3636
3803
|
warmth: { unit: "factor", default: 0.5, min: 0, max: 1 },
|
|
3637
3804
|
mix: { node: "_mix", field: "offset", unit: "factor", default: 1, min: 0, max: 1 }
|
|
3638
3805
|
};
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3806
|
+
var INPUT_SPAN2 = 16;
|
|
3807
|
+
var CURVE_LEN3 = 32769;
|
|
3808
|
+
var driveGain = (drive) => 0.25 * Math.pow(64, Math.max(0, Math.min(1, drive)));
|
|
3809
|
+
function saturationCurve(drive) {
|
|
3810
|
+
const g = driveGain(drive);
|
|
3811
|
+
const c = new Float32Array(CURVE_LEN3);
|
|
3812
|
+
for (let i = 0; i < CURVE_LEN3; i++) {
|
|
3813
|
+
const v = i * 2 / (CURVE_LEN3 - 1) - 1;
|
|
3814
|
+
c[i] = Math.tanh(g * INPUT_SPAN2 * v) / g;
|
|
3646
3815
|
}
|
|
3647
|
-
return
|
|
3816
|
+
return c;
|
|
3648
3817
|
}
|
|
3649
3818
|
var saturatorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
3650
3819
|
type: "saturator",
|
|
@@ -3661,29 +3830,29 @@ var saturatorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3661
3830
|
const output = ctx.createGain();
|
|
3662
3831
|
const dryGain = ctx.createGain();
|
|
3663
3832
|
const wetGain = ctx.createGain();
|
|
3664
|
-
const
|
|
3665
|
-
|
|
3833
|
+
const preGain = ctx.createGain();
|
|
3834
|
+
preGain.gain.value = 1 / INPUT_SPAN2;
|
|
3835
|
+
const shaper = createShaperNode(ctx, saturationCurve(module.drive));
|
|
3836
|
+
const dryTrim = ctx.createGain();
|
|
3837
|
+
dryTrim.gain.value = INPUT_SPAN2;
|
|
3666
3838
|
const warmthFilter = ctx.createBiquadFilter();
|
|
3667
|
-
driveGain.gain.value = 1 + module.drive * 4;
|
|
3668
|
-
waveshaper.curve = makeSaturationCurve(module.drive);
|
|
3669
|
-
waveshaper.oversample = "2x";
|
|
3670
3839
|
warmthFilter.type = "lowshelf";
|
|
3671
3840
|
warmthFilter.frequency.value = 300;
|
|
3672
3841
|
warmthFilter.gain.value = module.warmth * 6;
|
|
3673
3842
|
const _mix = createMix(ctx, dryGain, wetGain, module.mix, "linear");
|
|
3674
|
-
input.connect(
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
waveshaper.connect(warmthFilter);
|
|
3843
|
+
input.connect(preGain);
|
|
3844
|
+
preGain.connect(shaper);
|
|
3845
|
+
shaper.connect(warmthFilter, 0);
|
|
3678
3846
|
warmthFilter.connect(wetGain);
|
|
3847
|
+
shaper.connect(dryTrim, 1);
|
|
3848
|
+
dryTrim.connect(dryGain);
|
|
3679
3849
|
dryGain.connect(output);
|
|
3680
3850
|
wetGain.connect(output);
|
|
3681
|
-
return { input, output,
|
|
3851
|
+
return { input, output, preGain, shaper, dryTrim, warmthFilter, dryGain, wetGain, _mix };
|
|
3682
3852
|
},
|
|
3683
3853
|
updateParam(nodes, _m, param, value) {
|
|
3684
3854
|
if (param === "drive") {
|
|
3685
|
-
nodes.
|
|
3686
|
-
nodes.waveshaper.curve = makeSaturationCurve(value);
|
|
3855
|
+
nodes.shaper.port.postMessage({ curve: saturationCurve(value) });
|
|
3687
3856
|
} else if (param === "warmth") {
|
|
3688
3857
|
nodes.warmthFilter.gain.value = value * 6;
|
|
3689
3858
|
} else if (param === "mix") {
|
|
@@ -3693,7 +3862,11 @@ var saturatorDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3693
3862
|
});
|
|
3694
3863
|
|
|
3695
3864
|
// src/lib-runtime/generated/modules/saturator.wrapper.ts
|
|
3696
|
-
var Saturator = /* @__PURE__ */ defineModule(saturatorDescriptor
|
|
3865
|
+
var Saturator = /* @__PURE__ */ defineModule(saturatorDescriptor, {
|
|
3866
|
+
worklets: {
|
|
3867
|
+
"shaper": shaper_default
|
|
3868
|
+
}
|
|
3869
|
+
});
|
|
3697
3870
|
|
|
3698
3871
|
// src/lib/dsp/shimmerRegen.ts
|
|
3699
3872
|
var REGEN_HP_HZ = 300;
|
|
@@ -3703,13 +3876,13 @@ var SHIFTER_ENERGY = 0.75;
|
|
|
3703
3876
|
var REGEN_DELAY_S = 0.02;
|
|
3704
3877
|
var SHIFTER_SEEDS = [5370206, 739982445];
|
|
3705
3878
|
var UNISON_FLOOR = [
|
|
3706
|
-
[0.5, 0.
|
|
3707
|
-
[1, 0.
|
|
3708
|
-
[2, 0.
|
|
3709
|
-
[3, 0.
|
|
3710
|
-
[5, 0.
|
|
3711
|
-
[7, 0.
|
|
3712
|
-
[10, 0.
|
|
3879
|
+
[0.5, 0.58],
|
|
3880
|
+
[1, 0.67],
|
|
3881
|
+
[2, 0.73],
|
|
3882
|
+
[3, 0.77],
|
|
3883
|
+
[5, 0.79],
|
|
3884
|
+
[7, 0.77],
|
|
3885
|
+
[10, 0.72]
|
|
3713
3886
|
];
|
|
3714
3887
|
var UNISON_PITCH_SPAN = 0.75;
|
|
3715
3888
|
function unisonFloor(decay) {
|
|
@@ -3851,9 +4024,9 @@ function makeSoftLimitCurve(knee, drive) {
|
|
|
3851
4024
|
const k = 0.1 + knee * 0.9;
|
|
3852
4025
|
const driveMul = 1 + drive * 3;
|
|
3853
4026
|
for (let i = 0; i < samples; i++) {
|
|
3854
|
-
const x = (i * 2 / samples - 1) * driveMul;
|
|
3855
|
-
if (Math.abs(x) < k) {
|
|
3856
|
-
curve[i] = x;
|
|
4027
|
+
const x = (i * 2 / (samples - 1) - 1) * driveMul;
|
|
4028
|
+
if (Math.abs(x) < k || 1 - k < 1e-9) {
|
|
4029
|
+
curve[i] = Math.max(-1, Math.min(1, x));
|
|
3857
4030
|
} else {
|
|
3858
4031
|
const sign = x > 0 ? 1 : -1;
|
|
3859
4032
|
curve[i] = sign * (k + (1 - k) * Math.tanh((Math.abs(x) - k) / (1 - k)));
|
|
@@ -3874,25 +4047,28 @@ var softLimitDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3874
4047
|
createNodes(ctx, module) {
|
|
3875
4048
|
const input = ctx.createGain();
|
|
3876
4049
|
const output = ctx.createGain();
|
|
3877
|
-
const waveshaper = ctx.
|
|
4050
|
+
const waveshaper = createShaperNode(ctx, makeSoftLimitCurve(module.knee, module.drive), { dry: false });
|
|
3878
4051
|
const ceiling = ctx.createGain();
|
|
3879
|
-
waveshaper.curve = makeSoftLimitCurve(module.knee, module.drive);
|
|
3880
|
-
waveshaper.oversample = "2x";
|
|
3881
4052
|
ceiling.gain.value = Math.pow(10, module.ceiling / 20);
|
|
3882
4053
|
input.connect(waveshaper);
|
|
3883
|
-
waveshaper.connect(ceiling);
|
|
4054
|
+
waveshaper.connect(ceiling, 0);
|
|
3884
4055
|
ceiling.connect(output);
|
|
3885
4056
|
return { input, output, waveshaper, ceiling };
|
|
3886
4057
|
},
|
|
3887
4058
|
updateParam(nodes, m, param, value) {
|
|
3888
|
-
|
|
3889
|
-
|
|
4059
|
+
const port = nodes.waveshaper.port;
|
|
4060
|
+
if (param === "drive") port.postMessage({ curve: makeSoftLimitCurve(m.knee, value) });
|
|
4061
|
+
else if (param === "knee") port.postMessage({ curve: makeSoftLimitCurve(value, m.drive) });
|
|
3890
4062
|
else if (param === "ceiling") nodes.ceiling.gain.value = Math.pow(10, value / 20);
|
|
3891
4063
|
}
|
|
3892
4064
|
});
|
|
3893
4065
|
|
|
3894
4066
|
// src/lib-runtime/generated/modules/soft-limit.wrapper.ts
|
|
3895
|
-
var SoftLimiter = /* @__PURE__ */ defineModule(softLimitDescriptor
|
|
4067
|
+
var SoftLimiter = /* @__PURE__ */ defineModule(softLimitDescriptor, {
|
|
4068
|
+
worklets: {
|
|
4069
|
+
"shaper": shaper_default
|
|
4070
|
+
}
|
|
4071
|
+
});
|
|
3896
4072
|
|
|
3897
4073
|
// src/lib-runtime/generated/modules/spring-reverb.tsx
|
|
3898
4074
|
var params38 = {
|
|
@@ -3957,6 +4133,7 @@ var SpringReverb = /* @__PURE__ */ defineModule(springReverbDescriptor, {
|
|
|
3957
4133
|
// src/lib-runtime/generated/modules/stereo-spread.tsx
|
|
3958
4134
|
var params39 = {
|
|
3959
4135
|
spread: { unit: "factor", default: 0.7, min: 0, max: 1 },
|
|
4136
|
+
width: { node: "wetGain", field: "gain", unit: "factor", default: 1, min: 0, max: 2 },
|
|
3960
4137
|
center: { unit: "Hz", default: 800, min: 200, max: 2e3, scale: "log" }
|
|
3961
4138
|
};
|
|
3962
4139
|
var stereoSpreadDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
@@ -3972,12 +4149,11 @@ var stereoSpreadDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3972
4149
|
createNodes(ctx, module) {
|
|
3973
4150
|
const input = ctx.createGain();
|
|
3974
4151
|
const output = ctx.createGain();
|
|
3975
|
-
|
|
4152
|
+
input.connect(output);
|
|
3976
4153
|
const highpass = ctx.createBiquadFilter();
|
|
3977
|
-
lowpass.type = "lowpass";
|
|
3978
|
-
lowpass.frequency.value = module.center;
|
|
3979
4154
|
highpass.type = "highpass";
|
|
3980
4155
|
highpass.frequency.value = module.center;
|
|
4156
|
+
highpass.Q.value = -3.0102999566;
|
|
3981
4157
|
const panLeft = ctx.createStereoPanner();
|
|
3982
4158
|
const panRight = ctx.createStereoPanner();
|
|
3983
4159
|
const haasDelay = ctx.createDelay(0.02);
|
|
@@ -3986,8 +4162,6 @@ var stereoSpreadDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3986
4162
|
haasDelay.delayTime.value = module.spread * 5e-3;
|
|
3987
4163
|
const wetGain = ctx.createGain();
|
|
3988
4164
|
wetGain.gain.value = module.width;
|
|
3989
|
-
input.connect(lowpass);
|
|
3990
|
-
lowpass.connect(output);
|
|
3991
4165
|
input.connect(highpass);
|
|
3992
4166
|
highpass.connect(panLeft);
|
|
3993
4167
|
highpass.connect(haasDelay);
|
|
@@ -3995,7 +4169,7 @@ var stereoSpreadDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
3995
4169
|
panLeft.connect(wetGain);
|
|
3996
4170
|
panRight.connect(wetGain);
|
|
3997
4171
|
wetGain.connect(output);
|
|
3998
|
-
return { input, output,
|
|
4172
|
+
return { input, output, highpass, panLeft, panRight, haasDelay, wetGain };
|
|
3999
4173
|
},
|
|
4000
4174
|
updateParam(nodes, _m, param, value) {
|
|
4001
4175
|
if (param === "spread") {
|
|
@@ -4005,7 +4179,6 @@ var stereoSpreadDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
4005
4179
|
} else if (param === "width") {
|
|
4006
4180
|
nodes.wetGain.gain.value = value;
|
|
4007
4181
|
} else if (param === "center") {
|
|
4008
|
-
nodes.lowpass.frequency.value = value;
|
|
4009
4182
|
nodes.highpass.frequency.value = value;
|
|
4010
4183
|
}
|
|
4011
4184
|
}
|
|
@@ -4502,12 +4675,13 @@ var Vco = /* @__PURE__ */ defineModule(oscillatorDescriptor, {
|
|
|
4502
4675
|
});
|
|
4503
4676
|
|
|
4504
4677
|
// src/lib-runtime/generated/modules/wah.tsx
|
|
4678
|
+
var DEPTH_ST = 18;
|
|
4505
4679
|
var params48 = {
|
|
4506
4680
|
note: { node: "_cutoffVoct", field: "transpose", unit: "note", default: 79, min: 55, max: 95 },
|
|
4507
4681
|
// Resonance drives both the filter Q and a separate makeup gain — a split, so it stays set-only.
|
|
4508
4682
|
resonance: { unit: "factor", default: 8, min: 1, max: 20, scale: "log" },
|
|
4509
4683
|
rate: { node: "lfo", field: "frequency", unit: "Hz", default: 1, min: 0.1, max: 10, scale: "log" },
|
|
4510
|
-
// Depth is stored 0-1 but scaled by
|
|
4684
|
+
// Depth is stored 0-1 but scaled by DEPTH_ST semitones onto lfoGain.gain — a conversion, so set-only.
|
|
4511
4685
|
depth: { unit: "factor", default: 0.6, min: 0, max: 1 }
|
|
4512
4686
|
};
|
|
4513
4687
|
var wahDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
@@ -4541,7 +4715,7 @@ var wahDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
4541
4715
|
_cutoffVoct.connect(filter.frequency);
|
|
4542
4716
|
lfo.type = "sine";
|
|
4543
4717
|
lfo.frequency.value = module.rate;
|
|
4544
|
-
lfoGain.gain.value = module.depth *
|
|
4718
|
+
lfoGain.gain.value = module.depth * DEPTH_ST;
|
|
4545
4719
|
lfo.connect(lfoGain);
|
|
4546
4720
|
lfoGain.connect(_cutoffVoct);
|
|
4547
4721
|
lfo.start();
|
|
@@ -4560,7 +4734,7 @@ var wahDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
4560
4734
|
} else if (param === "rate") {
|
|
4561
4735
|
nodes.lfo.frequency.value = value;
|
|
4562
4736
|
} else if (param === "depth") {
|
|
4563
|
-
nodes.lfoGain.gain.value = value *
|
|
4737
|
+
nodes.lfoGain.gain.value = value * DEPTH_ST;
|
|
4564
4738
|
}
|
|
4565
4739
|
},
|
|
4566
4740
|
dispose(nodes) {
|
|
@@ -4618,20 +4792,18 @@ var wavefolderDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
4618
4792
|
const output = ctx.createGain();
|
|
4619
4793
|
const dryGain = ctx.createGain();
|
|
4620
4794
|
const wetGain = ctx.createGain();
|
|
4621
|
-
const waveshaper = ctx.
|
|
4622
|
-
waveshaper.curve = makeWavefoldCurve(module.folds, module.symmetry);
|
|
4623
|
-
waveshaper.oversample = "4x";
|
|
4795
|
+
const waveshaper = createShaperNode(ctx, makeWavefoldCurve(module.folds, module.symmetry));
|
|
4624
4796
|
const _mix = createMix(ctx, dryGain, wetGain, module.mix, "linear");
|
|
4625
|
-
input.connect(dryGain);
|
|
4626
4797
|
input.connect(waveshaper);
|
|
4627
|
-
waveshaper.connect(
|
|
4798
|
+
waveshaper.connect(dryGain, 1);
|
|
4799
|
+
waveshaper.connect(wetGain, 0);
|
|
4628
4800
|
dryGain.connect(output);
|
|
4629
4801
|
wetGain.connect(output);
|
|
4630
4802
|
return { input, output, waveshaper, dryGain, wetGain, _mix };
|
|
4631
4803
|
},
|
|
4632
4804
|
updateParam(nodes, module, param, value) {
|
|
4633
4805
|
if (param === "folds" || param === "symmetry") {
|
|
4634
|
-
nodes.waveshaper.curve
|
|
4806
|
+
nodes.waveshaper.port.postMessage({ curve: makeWavefoldCurve(module.folds, module.symmetry) });
|
|
4635
4807
|
} else if (param === "mix") {
|
|
4636
4808
|
nodes._mix.offset.value = value;
|
|
4637
4809
|
}
|
|
@@ -4639,7 +4811,11 @@ var wavefolderDescriptor = /* @__PURE__ */ defineDescriptor({
|
|
|
4639
4811
|
});
|
|
4640
4812
|
|
|
4641
4813
|
// src/lib-runtime/generated/modules/wavefolder.wrapper.ts
|
|
4642
|
-
var Wavefolder = /* @__PURE__ */ defineModule(wavefolderDescriptor
|
|
4814
|
+
var Wavefolder = /* @__PURE__ */ defineModule(wavefolderDescriptor, {
|
|
4815
|
+
worklets: {
|
|
4816
|
+
"shaper": shaper_default
|
|
4817
|
+
}
|
|
4818
|
+
});
|
|
4643
4819
|
export {
|
|
4644
4820
|
AcidFilter,
|
|
4645
4821
|
AutoPan,
|