superdough
Version:
simple web audio synth and sampler intended for live coding. inspired by superdirt and webdirt.
1,055 lines • 54.1 kB
JavaScript
import { map as Zn } from "nanostores";
if (typeof DelayNode < "u") {
class e extends DelayNode {
constructor(t, o, c, g) {
super(t), o = Math.abs(o), this.delayTime.value = c;
const s = t.createGain();
s.gain.value = Math.min(Math.abs(g), 0.995), this.feedback = s.gain;
const a = t.createGain();
return a.gain.value = o, this.delayGain = a, this.connect(s), this.connect(a), s.connect(this), this.connect = (I) => a.connect(I), this;
}
start(t) {
this.delayGain.gain.setValueAtTime(this.delayGain.gain.value, t + this.delayTime.value);
}
}
AudioContext.prototype.createFeedbackDelay = function(n, t, o) {
return new e(this, n, t, o);
};
}
var fe = {};
fe.generateReverb = function(e, n) {
for (var t = e.audioContext || new AudioContext(), o = t.sampleRate, c = e.numChannels || 2, g = e.decayTime * 1.5, s = Math.round(e.decayTime * o), a = Math.round(g * o), I = Math.round((e.fadeInTime || 0) * o), i = Math.pow(1 / 1e3, 1 / s), r = t.createBuffer(c, a, o), d = 0; d < c; d++) {
for (var l = r.getChannelData(d), C = 0; C < a; C++)
l[C] = wn() * Math.pow(i, C);
for (var C = 0; C < I; C++)
l[C] *= C / I;
}
yn(r, e.lpFreqStart || 0, e.lpFreqEnd || 0, e.decayTime, n);
};
fe.generateGraph = function(e, n, t, o, c) {
var g = document.createElement("canvas");
g.width = n, g.height = t;
var s = g.getContext("2d");
s.fillStyle = "#000", s.fillRect(0, 0, g.width, g.height), s.fillStyle = "#fff";
for (var a = n / e.length, I = t / (c - o), i = 0; i < e.length; i++)
s.fillRect(i * a, t - (e[i] - o) * I, 1, 1);
return g;
};
var yn = function(e, n, t, o, c) {
if (n == 0) {
c(e);
return;
}
var g = Xn(e), s = new OfflineAudioContext(e.numberOfChannels, g[0].length, e.sampleRate), a = s.createBufferSource();
a.buffer = e;
var I = s.createBiquadFilter();
n = Math.min(n, e.sampleRate / 2), t = Math.min(t, e.sampleRate / 2), I.type = "lowpass", I.Q.value = 1e-4, I.frequency.setValueAtTime(n, 0), I.frequency.linearRampToValueAtTime(t, o), a.connect(I), I.connect(s.destination), a.start(), s.oncomplete = function(i) {
c(i.renderedBuffer);
}, s.startRendering(), window.filterNode = I;
}, Xn = function(e) {
for (var n = [], t = 0; t < e.numberOfChannels; t++)
n[t] = e.getChannelData(t);
return n;
}, wn = function() {
return Math.random() * 2 - 1;
};
typeof AudioContext < "u" && (AudioContext.prototype.adjustLength = function(e, n) {
const t = n.sampleRate * e, o = this.createBuffer(n.numberOfChannels, n.length, n.sampleRate);
for (let c = 0; c < n.numberOfChannels; c++) {
let g = n.getChannelData(c), s = o.getChannelData(c);
for (let a = 0; a < t; a++)
s[a] = g[a] || 0;
}
return o;
}, AudioContext.prototype.createReverb = function(e, n, t, o, c) {
const g = this.createConvolver();
return g.generate = (s = 2, a = 0.1, I = 15e3, i = 1e3, r) => {
g.duration = s, g.fade = a, g.lp = I, g.dim = i, g.ir = r, r ? g.buffer = this.adjustLength(s, r) : fe.generateReverb(
{
audioContext: this,
numChannels: 2,
decayTime: s,
fadeInTime: a,
lpFreqStart: I,
lpFreqEnd: i
},
(d) => {
g.buffer = d;
}
);
}, g.generate(e, n, t, o, c), g;
});
var Oe = {
a: { freqs: [660, 1120, 2750, 3e3, 3350], gains: [1, 0.5012, 0.0708, 0.0631, 0.0126], qs: [80, 90, 120, 130, 140] },
e: { freqs: [440, 1800, 2700, 3e3, 3300], gains: [1, 0.1995, 0.1259, 0.1, 0.1], qs: [70, 80, 100, 120, 120] },
i: { freqs: [270, 1850, 2900, 3350, 3590], gains: [1, 0.0631, 0.0631, 0.0158, 0.0158], qs: [40, 90, 100, 120, 120] },
o: { freqs: [430, 820, 2700, 3e3, 3300], gains: [1, 0.3162, 0.0501, 0.0794, 0.01995], qs: [40, 80, 100, 120, 120] },
u: { freqs: [370, 630, 2750, 3e3, 3400], gains: [1, 0.1, 0.0708, 0.0316, 0.01995], qs: [40, 60, 100, 120, 120] },
ae: { freqs: [650, 1515, 2400, 3e3, 3350], gains: [1, 0.5, 0.1008, 0.0631, 0.0126], qs: [80, 90, 120, 130, 140] },
aa: { freqs: [560, 900, 2570, 3e3, 3300], gains: [1, 0.5, 0.0708, 0.0631, 0.0126], qs: [80, 90, 120, 130, 140] },
oe: { freqs: [500, 1430, 2300, 3e3, 3300], gains: [1, 0.2, 0.0708, 0.0316, 0.01995], qs: [40, 60, 100, 120, 120] },
ue: { freqs: [250, 1750, 2150, 3200, 3300], gains: [1, 0.1, 0.0708, 0.0316, 0.01995], qs: [40, 60, 100, 120, 120] },
y: { freqs: [400, 1460, 2400, 3e3, 3300], gains: [1, 0.2, 0.0708, 0.0316, 0.02995], qs: [40, 60, 100, 120, 120] },
uh: { freqs: [600, 1250, 2100, 3100, 3500], gains: [1, 0.3, 0.0608, 0.0316, 0.01995], qs: [40, 70, 100, 120, 130] },
un: { freqs: [500, 1240, 2280, 3e3, 3500], gains: [1, 0.1, 0.1708, 0.0216, 0.02995], qs: [40, 60, 100, 120, 120] },
en: { freqs: [600, 1480, 2450, 3200, 3300], gains: [1, 0.15, 0.0708, 0.0316, 0.02995], qs: [40, 60, 100, 120, 120] },
an: { freqs: [700, 1050, 2500, 3e3, 3300], gains: [1, 0.1, 0.0708, 0.0316, 0.02995], qs: [40, 60, 100, 120, 120] },
on: { freqs: [500, 1080, 2350, 3e3, 3300], gains: [1, 0.1, 0.0708, 0.0316, 0.02995], qs: [40, 60, 100, 120, 120] },
get æ() {
return this.ae;
},
get ø() {
return this.oe;
},
get ɑ() {
return this.aa;
},
get å() {
return this.aa;
},
get ö() {
return this.oe;
},
get ü() {
return this.ue;
},
get ı() {
return this.y;
}
};
if (typeof GainNode < "u") {
class e extends GainNode {
constructor(t, o) {
if (super(t), !Oe[o])
throw new Error("vowel: unknown vowel " + o);
const { gains: c, qs: g, freqs: s } = Oe[o], a = t.createGain();
for (let I = 0; I < 5; I++) {
const i = t.createGain();
i.gain.value = c[I];
const r = t.createBiquadFilter();
r.type = "bandpass", r.Q.value = g[I], r.frequency.value = s[I], this.connect(r), r.connect(i), i.connect(a);
}
return a.gain.value = 8, this.connect = (I) => a.connect(I), this;
}
}
AudioContext.prototype.createVowelFilter = function(n) {
return new e(this, n);
};
}
let qe = (e) => console.log(e);
const v = (...e) => qe(...e), dt = (e) => {
qe = e;
}, Vn = (e) => {
if (typeof e != "string")
return [];
const [n, t = "", o] = e.match(/^([a-gA-G])([#bsf]*)([0-9]*)$/)?.slice(1) || [];
return n ? [n, t, o ? Number(o) : void 0] : [];
}, Wn = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 }, Hn = { "#": 1, b: -1, s: 1, f: -1 }, ie = (e, n = 3) => {
const [t, o, c = n] = Vn(e);
if (!t)
throw new Error('not a note: "' + e + '"');
const g = Wn[t.toLowerCase()], s = o?.split("").reduce((a, I) => a + Hn[I], 0) || 0;
return (Number(c) + 1) * 12 + g + s;
}, Pe = (e) => Math.pow(2, (e - 69) / 12) * 440, ne = (e, n, t) => Math.min(Math.max(e, n), t), Nn = (e) => 12 * Math.log(e / 440) / Math.LN2 + 69, Kn = (e, n) => {
if (typeof e != "object")
throw new Error("valueToMidi: expected object value");
let { freq: t, note: o } = e;
if (typeof t == "number")
return Nn(t);
if (typeof o == "string")
return ie(o);
if (typeof o == "number")
return o;
if (!n)
throw new Error("valueToMidi: expected freq or note to be set");
return n;
};
function J(e, n = 0, t) {
return isNaN(Number(e)) ? (!t && v(`"${e}" is not a number, falling back to ${n}`, "warning"), n) : e;
}
const _e = (e, n) => (e % n + n) % n, je = (e, n) => _e(Math.round(J(e, 0)), n), Yn = "data:application/javascript;base64,Ly8gY29hcnNlLCBjcnVzaCwgYW5kIHNoYXBlIHByb2Nlc3NvcnMgYWRhcHRlZCBmcm9tIGRrdHIwJ3Mgd2ViZGlydDogaHR0cHM6Ly9naXRodWIuY29tL2RrdHIwL1dlYkRpcnQvYmxvYi81Y2UzZDY5ODM2MmM1NGQ2ZTFiNjhhY2M0N2ViMjk1NWFjNjJjNzkzL2Rpc3QvQXVkaW9Xb3JrbGV0cy5qcwovLyBMSUNFTlNFIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHYzLjAgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9ka3RyMC9XZWJEaXJ0L2Jsb2IvbWFpbi9MSUNFTlNFCi8vIFRPRklYOiBUSElTIEZJTEUgRE9FUyBOT1QgU1VQUE9SVCBJTVBPUlRTIE9OIERFUE9MWU1FTlQKY29uc3QgY2xhbXAgPSAobnVtLCBtaW4sIG1heCkgPT4gTWF0aC5taW4oTWF0aC5tYXgobnVtLCBtaW4pLCBtYXgpOwpjb25zdCBfbW9kID0gKG4sIG0pID0+ICgobiAlIG0pICsgbSkgJSBtOwoKY29uc3QgYmxvY2tTaXplID0gMTI4OwovLyBhZGp1c3Qgd2F2ZXNoYXBlIHRvIHJlbW92ZSBmcmVxdWVuY2llcyBhYm92ZSBueXF1aXN0IHRvIHByZXZlbnQgYWxpYXNpbmcKLy8gcmVmZXJlbmNlZCBmcm9tIGh0dHBzOi8vd3d3Lmt2cmF1ZGlvLmNvbS9mb3J1bS92aWV3dG9waWMucGhwP3Q9Mzc1NTE3CmZ1bmN0aW9uIHBvbHlCbGVwKHBoYXNlLCBkdCkgewogIC8vIDAgPD0gcGhhc2UgPCAxCiAgaWYgKHBoYXNlIDwgZHQpIHsKICAgIHBoYXNlIC89IGR0OwogICAgLy8gMiAqIChwaGFzZSAtIHBoYXNlXjIvMiAtIDAuNSkKICAgIHJldHVybiBwaGFzZSArIHBoYXNlIC0gcGhhc2UgKiBwaGFzZSAtIDE7CiAgfQoKICAvLyAtMSA8IHBoYXNlIDwgMAogIGVsc2UgaWYgKHBoYXNlID4gMSAtIGR0KSB7CiAgICBwaGFzZSA9IChwaGFzZSAtIDEpIC8gZHQ7CiAgICAvLyAyICogKHBoYXNlXjIvMiArIHBoYXNlICsgMC41KQogICAgcmV0dXJuIHBoYXNlICogcGhhc2UgKyBwaGFzZSArIHBoYXNlICsgMTsKICB9CgogIC8vIDAgb3RoZXJ3aXNlCiAgZWxzZSB7CiAgICByZXR1cm4gMDsKICB9Cn0KCmNvbnN0IHdhdmVzaGFwZXMgPSB7CiAgdHJpKHBoYXNlLCBza2V3ID0gMC41KSB7CiAgICBjb25zdCB4ID0gMSAtIHNrZXc7CiAgICBpZiAocGhhc2UgPj0gc2tldykgewogICAgICByZXR1cm4gMSAvIHggLSBwaGFzZSAvIHg7CiAgICB9CiAgICByZXR1cm4gcGhhc2UgLyBza2V3OwogIH0sCiAgc2luZShwaGFzZSkgewogICAgcmV0dXJuIE1hdGguc2luKE1hdGguUEkgKiAyICogcGhhc2UpICogMC41ICsgMC41OwogIH0sCiAgcmFtcChwaGFzZSkgewogICAgcmV0dXJuIHBoYXNlOwogIH0sCiAgc2F3KHBoYXNlKSB7CiAgICByZXR1cm4gMSAtIHBoYXNlOwogIH0sCgogIHNxdWFyZShwaGFzZSwgc2tldyA9IDAuNSkgewogICAgaWYgKHBoYXNlID49IHNrZXcpIHsKICAgICAgcmV0dXJuIDA7CiAgICB9CiAgICByZXR1cm4gMTsKICB9LAogIGN1c3RvbShwaGFzZSwgdmFsdWVzID0gWzAsIDFdKSB7CiAgICBjb25zdCBudW1QYXJ0cyA9IHZhbHVlcy5sZW5ndGggLSAxOwogICAgY29uc3QgY3VyclBhcnQgPSBNYXRoLmZsb29yKHBoYXNlICogbnVtUGFydHMpOwoKICAgIGNvbnN0IHBhcnRMZW5ndGggPSAxIC8gbnVtUGFydHM7CiAgICBjb25zdCBzdGFydFZhbCA9IGNsYW1wKHZhbHVlc1tjdXJyUGFydF0sIDAsIDEpOwogICAgY29uc3QgZW5kVmFsID0gY2xhbXAodmFsdWVzW2N1cnJQYXJ0ICsgMV0sIDAsIDEpOwogICAgY29uc3QgeTIgPSBlbmRWYWw7CiAgICBjb25zdCB5MSA9IHN0YXJ0VmFsOwogICAgY29uc3QgeDEgPSAwOwogICAgY29uc3QgeDIgPSBwYXJ0TGVuZ3RoOwogICAgY29uc3Qgc2xvcGUgPSAoeTIgLSB5MSkgLyAoeDIgLSB4MSk7CiAgICByZXR1cm4gc2xvcGUgKiAocGhhc2UgLSBwYXJ0TGVuZ3RoICogY3VyclBhcnQpICsgc3RhcnRWYWw7CiAgfSwKICBzYXdibGVwKHBoYXNlLCBkdCkgewogICAgY29uc3QgdiA9IDIgKiBwaGFzZSAtIDE7CiAgICByZXR1cm4gdiAtIHBvbHlCbGVwKHBoYXNlLCBkdCk7CiAgfSwKfTsKCmNvbnN0IHdhdmVTaGFwZU5hbWVzID0gT2JqZWN0LmtleXMod2F2ZXNoYXBlcyk7CmNsYXNzIExGT1Byb2Nlc3NvciBleHRlbmRzIEF1ZGlvV29ya2xldFByb2Nlc3NvciB7CiAgc3RhdGljIGdldCBwYXJhbWV0ZXJEZXNjcmlwdG9ycygpIHsKICAgIHJldHVybiBbCiAgICAgIHsgbmFtZTogJ3RpbWUnLCBkZWZhdWx0VmFsdWU6IDAgfSwKICAgICAgeyBuYW1lOiAnZW5kJywgZGVmYXVsdFZhbHVlOiAwIH0sCiAgICAgIHsgbmFtZTogJ2ZyZXF1ZW5jeScsIGRlZmF1bHRWYWx1ZTogMC41IH0sCiAgICAgIHsgbmFtZTogJ3NrZXcnLCBkZWZhdWx0VmFsdWU6IDAuNSB9LAogICAgICB7IG5hbWU6ICdkZXB0aCcsIGRlZmF1bHRWYWx1ZTogMSB9LAogICAgICB7IG5hbWU6ICdwaGFzZW9mZnNldCcsIGRlZmF1bHRWYWx1ZTogMCB9LAogICAgICB7IG5hbWU6ICdzaGFwZScsIGRlZmF1bHRWYWx1ZTogMCB9LAogICAgICB7IG5hbWU6ICdkY29mZnNldCcsIGRlZmF1bHRWYWx1ZTogMCB9LAogICAgXTsKICB9CgogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoKTsKICAgIHRoaXMucGhhc2U7CiAgfQoKICBpbmNyZW1lbnRQaGFzZShkdCkgewogICAgdGhpcy5waGFzZSArPSBkdDsKICAgIGlmICh0aGlzLnBoYXNlID4gMS4wKSB7CiAgICAgIHRoaXMucGhhc2UgPSB0aGlzLnBoYXNlIC0gMTsKICAgIH0KICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWYKICAgIGlmIChjdXJyZW50VGltZSA+PSBwYXJhbWV0ZXJzLmVuZFswXSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0c1swXTsKICAgIGNvbnN0IGZyZXF1ZW5jeSA9IHBhcmFtZXRlcnNbJ2ZyZXF1ZW5jeSddWzBdOwoKICAgIGNvbnN0IHRpbWUgPSBwYXJhbWV0ZXJzWyd0aW1lJ11bMF07CiAgICBjb25zdCBkZXB0aCA9IHBhcmFtZXRlcnNbJ2RlcHRoJ11bMF07CiAgICBjb25zdCBza2V3ID0gcGFyYW1ldGVyc1snc2tldyddWzBdOwogICAgY29uc3QgcGhhc2VvZmZzZXQgPSBwYXJhbWV0ZXJzWydwaGFzZW9mZnNldCddWzBdOwoKICAgIGNvbnN0IGRjb2Zmc2V0ID0gcGFyYW1ldGVyc1snZGNvZmZzZXQnXVswXTsKICAgIGNvbnN0IHNoYXBlID0gd2F2ZVNoYXBlTmFtZXNbcGFyYW1ldGVyc1snc2hhcGUnXVswXV07CgogICAgY29uc3QgYmxvY2tTaXplID0gb3V0cHV0WzBdLmxlbmd0aCA/PyAwOwoKICAgIGlmICh0aGlzLnBoYXNlID09IG51bGwpIHsKICAgICAgdGhpcy5waGFzZSA9IF9tb2QodGltZSAqIGZyZXF1ZW5jeSArIHBoYXNlb2Zmc2V0LCAxKTsKICAgIH0KICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlZgogICAgY29uc3QgZHQgPSBmcmVxdWVuY3kgLyBzYW1wbGVSYXRlOwogICAgZm9yIChsZXQgbiA9IDA7IG4gPCBibG9ja1NpemU7IG4rKykgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dC5sZW5ndGg7IGkrKykgewogICAgICAgIGNvbnN0IG1vZHZhbCA9ICh3YXZlc2hhcGVzW3NoYXBlXSh0aGlzLnBoYXNlLCBza2V3KSArIGRjb2Zmc2V0KSAqIGRlcHRoOwogICAgICAgIG91dHB1dFtpXVtuXSA9IG1vZHZhbDsKICAgICAgfQogICAgICB0aGlzLmluY3JlbWVudFBoYXNlKGR0KTsKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KcmVnaXN0ZXJQcm9jZXNzb3IoJ2xmby1wcm9jZXNzb3InLCBMRk9Qcm9jZXNzb3IpOwoKY2xhc3MgQ29hcnNlUHJvY2Vzc29yIGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewogICAgcmV0dXJuIFt7IG5hbWU6ICdjb2Fyc2UnLCBkZWZhdWx0VmFsdWU6IDEgfV07CiAgfQoKICBjb25zdHJ1Y3RvcigpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLnN0YXJ0ZWQgPSBmYWxzZTsKICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBpbnB1dCA9IGlucHV0c1swXTsKICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dHNbMF07CgogICAgY29uc3QgaGFzSW5wdXQgPSAhKGlucHV0WzBdID09PSB1bmRlZmluZWQpOwogICAgaWYgKHRoaXMuc3RhcnRlZCAmJiAhaGFzSW5wdXQpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGhpcy5zdGFydGVkID0gaGFzSW5wdXQ7CgogICAgbGV0IGNvYXJzZSA9IHBhcmFtZXRlcnMuY29hcnNlWzBdID8/IDA7CiAgICBjb2Fyc2UgPSBNYXRoLm1heCgxLCBjb2Fyc2UpOwogICAgZm9yIChsZXQgbiA9IDA7IG4gPCBibG9ja1NpemU7IG4rKykgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgb3V0cHV0W2ldW25dID0gbiAlIGNvYXJzZSA9PT0gMCA/IGlucHV0W2ldW25dIDogb3V0cHV0W2ldW24gLSAxXTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfQp9CnJlZ2lzdGVyUHJvY2Vzc29yKCdjb2Fyc2UtcHJvY2Vzc29yJywgQ29hcnNlUHJvY2Vzc29yKTsKCmNsYXNzIENydXNoUHJvY2Vzc29yIGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewogICAgcmV0dXJuIFt7IG5hbWU6ICdjcnVzaCcsIGRlZmF1bHRWYWx1ZTogMCB9XTsKICB9CgogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuc3RhcnRlZCA9IGZhbHNlOwogIH0KCiAgcHJvY2VzcyhpbnB1dHMsIG91dHB1dHMsIHBhcmFtZXRlcnMpIHsKICAgIGNvbnN0IGlucHV0ID0gaW5wdXRzWzBdOwogICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0c1swXTsKCiAgICBjb25zdCBoYXNJbnB1dCA9ICEoaW5wdXRbMF0gPT09IHVuZGVmaW5lZCk7CiAgICBpZiAodGhpcy5zdGFydGVkICYmICFoYXNJbnB1dCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICB0aGlzLnN0YXJ0ZWQgPSBoYXNJbnB1dDsKCiAgICBsZXQgY3J1c2ggPSBwYXJhbWV0ZXJzLmNydXNoWzBdID8/IDg7CiAgICBjcnVzaCA9IE1hdGgubWF4KDEsIGNydXNoKTsKCiAgICBmb3IgKGxldCBuID0gMDsgbiA8IGJsb2NrU2l6ZTsgbisrKSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXQubGVuZ3RoOyBpKyspIHsKICAgICAgICBjb25zdCB4ID0gTWF0aC5wb3coMiwgY3J1c2ggLSAxKTsKICAgICAgICBvdXRwdXRbaV1bbl0gPSBNYXRoLnJvdW5kKGlucHV0W2ldW25dICogeCkgLyB4OwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KcmVnaXN0ZXJQcm9jZXNzb3IoJ2NydXNoLXByb2Nlc3NvcicsIENydXNoUHJvY2Vzc29yKTsKCmNsYXNzIFNoYXBlUHJvY2Vzc29yIGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewogICAgcmV0dXJuIFsKICAgICAgeyBuYW1lOiAnc2hhcGUnLCBkZWZhdWx0VmFsdWU6IDAgfSwKICAgICAgeyBuYW1lOiAncG9zdGdhaW4nLCBkZWZhdWx0VmFsdWU6IDEgfSwKICAgIF07CiAgfQoKICBjb25zdHJ1Y3RvcigpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLnN0YXJ0ZWQgPSBmYWxzZTsKICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBpbnB1dCA9IGlucHV0c1swXTsKICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dHNbMF07CgogICAgY29uc3QgaGFzSW5wdXQgPSAhKGlucHV0WzBdID09PSB1bmRlZmluZWQpOwogICAgaWYgKHRoaXMuc3RhcnRlZCAmJiAhaGFzSW5wdXQpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGhpcy5zdGFydGVkID0gaGFzSW5wdXQ7CgogICAgbGV0IHNoYXBlID0gcGFyYW1ldGVycy5zaGFwZVswXTsKICAgIHNoYXBlID0gc2hhcGUgPCAxID8gc2hhcGUgOiAxLjAgLSA0ZS0xMDsKICAgIHNoYXBlID0gKDIuMCAqIHNoYXBlKSAvICgxLjAgLSBzaGFwZSk7CiAgICBjb25zdCBwb3N0Z2FpbiA9IE1hdGgubWF4KDAuMDAxLCBNYXRoLm1pbigxLCBwYXJhbWV0ZXJzLnBvc3RnYWluWzBdKSk7CgogICAgZm9yIChsZXQgbiA9IDA7IG4gPCBibG9ja1NpemU7IG4rKykgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgb3V0cHV0W2ldW25dID0gKCgoMSArIHNoYXBlKSAqIGlucHV0W2ldW25dKSAvICgxICsgc2hhcGUgKiBNYXRoLmFicyhpbnB1dFtpXVtuXSkpKSAqIHBvc3RnYWluOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KcmVnaXN0ZXJQcm9jZXNzb3IoJ3NoYXBlLXByb2Nlc3NvcicsIFNoYXBlUHJvY2Vzc29yKTsKCmZ1bmN0aW9uIGZhc3RfdGFuaCh4KSB7CiAgY29uc3QgeDIgPSB4ICogeDsKICByZXR1cm4gKHggKiAoMjcuMCArIHgyKSkgLyAoMjcuMCArIDkuMCAqIHgyKTsKfQpjb25zdCBfUEkgPSAzLjE0MTU5MjY1MzU5OwovL2FkYXB0ZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vVGhlQm91dGVpbGxhY0JlYXIvd2ViYXVkaW93b3JrbGV0LXdhc20/dGFiPU1JVC0xLW92LWZpbGUKY2xhc3MgTGFkZGVyUHJvY2Vzc29yIGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewogICAgcmV0dXJuIFsKICAgICAgeyBuYW1lOiAnZnJlcXVlbmN5JywgZGVmYXVsdFZhbHVlOiA1MDAgfSwKICAgICAgeyBuYW1lOiAncScsIGRlZmF1bHRWYWx1ZTogMSB9LAogICAgICB7IG5hbWU6ICdkcml2ZScsIGRlZmF1bHRWYWx1ZTogMC42OSB9LAogICAgXTsKICB9CgogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuc3RhcnRlZCA9IGZhbHNlOwogICAgdGhpcy5wMCA9IFswLCAwXTsKICAgIHRoaXMucDEgPSBbMCwgMF07CiAgICB0aGlzLnAyID0gWzAsIDBdOwogICAgdGhpcy5wMyA9IFswLCAwXTsKICAgIHRoaXMucDMyID0gWzAsIDBdOwogICAgdGhpcy5wMzMgPSBbMCwgMF07CiAgICB0aGlzLnAzNCA9IFswLCAwXTsKICB9CgogIHByb2Nlc3MoaW5wdXRzLCBvdXRwdXRzLCBwYXJhbWV0ZXJzKSB7CiAgICBjb25zdCBpbnB1dCA9IGlucHV0c1swXTsKICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dHNbMF07CgogICAgY29uc3QgaGFzSW5wdXQgPSAhKGlucHV0WzBdID09PSB1bmRlZmluZWQpOwogICAgaWYgKHRoaXMuc3RhcnRlZCAmJiAhaGFzSW5wdXQpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIHRoaXMuc3RhcnRlZCA9IGhhc0lucHV0OwoKICAgIGNvbnN0IHJlc29uYW5jZSA9IHBhcmFtZXRlcnMucVswXTsKICAgIGNvbnN0IGRyaXZlID0gY2xhbXAoTWF0aC5leHAocGFyYW1ldGVycy5kcml2ZVswXSksIDAuMSwgMjAwMCk7CgogICAgbGV0IGN1dG9mZiA9IHBhcmFtZXRlcnMuZnJlcXVlbmN5WzBdOwogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVmCiAgICBjdXRvZmYgPSAoY3V0b2ZmICogMiAqIF9QSSkgLyBzYW1wbGVSYXRlOwogICAgY3V0b2ZmID0gY3V0b2ZmID4gMSA/IDEgOiBjdXRvZmY7CgogICAgY29uc3QgayA9IE1hdGgubWluKDgsIHJlc29uYW5jZSAqIDAuNCk7CiAgICAvLyAgICAgICAgICAgICAgIGRyaXZlIG1ha2V1cCAgKiByZXNvbmFuY2Ugdm9sdW1lIGxvc3MgbWFrZXVwCiAgICBsZXQgbWFrZXVwZ2FpbiA9ICgxIC8gZHJpdmUpICogTWF0aC5taW4oMS43NSwgMSArIGspOwoKICAgIGZvciAobGV0IG4gPSAwOyBuIDwgYmxvY2tTaXplOyBuKyspIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dC5sZW5ndGg7IGkrKykgewogICAgICAgIGNvbnN0IG91dCA9IHRoaXMucDNbaV0gKiAwLjM2MDg5MSArIHRoaXMucDMyW2ldICogMC40MTcyOSArIHRoaXMucDMzW2ldICogMC4xNzc4OTYgKyB0aGlzLnAzNFtpXSAqIDAuMDQzOTcyNTsKCiAgICAgICAgdGhpcy5wMzRbaV0gPSB0aGlzLnAzM1tpXTsKICAgICAgICB0aGlzLnAzM1tpXSA9IHRoaXMucDMyW2ldOwogICAgICAgIHRoaXMucDMyW2ldID0gdGhpcy5wM1tpXTsKCiAgICAgICAgdGhpcy5wMFtpXSArPSAoZmFzdF90YW5oKGlucHV0W2ldW25dICogZHJpdmUgLSBrICogb3V0KSAtIGZhc3RfdGFuaCh0aGlzLnAwW2ldKSkgKiBjdXRvZmY7CiAgICAgICAgdGhpcy5wMVtpXSArPSAoZmFzdF90YW5oKHRoaXMucDBbaV0pIC0gZmFzdF90YW5oKHRoaXMucDFbaV0pKSAqIGN1dG9mZjsKICAgICAgICB0aGlzLnAyW2ldICs9IChmYXN0X3RhbmgodGhpcy5wMVtpXSkgLSBmYXN0X3RhbmgodGhpcy5wMltpXSkpICogY3V0b2ZmOwogICAgICAgIHRoaXMucDNbaV0gKz0gKGZhc3RfdGFuaCh0aGlzLnAyW2ldKSAtIGZhc3RfdGFuaCh0aGlzLnAzW2ldKSkgKiBjdXRvZmY7CgogICAgICAgIG91dHB1dFtpXVtuXSA9IG91dCAqIG1ha2V1cGdhaW47CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KfQpyZWdpc3RlclByb2Nlc3NvcignbGFkZGVyLXByb2Nlc3NvcicsIExhZGRlclByb2Nlc3Nvcik7CgpjbGFzcyBEaXN0b3J0UHJvY2Vzc29yIGV4dGVuZHMgQXVkaW9Xb3JrbGV0UHJvY2Vzc29yIHsKICBzdGF0aWMgZ2V0IHBhcmFtZXRlckRlc2NyaXB0b3JzKCkgewogICAgcmV0dXJuIFsKICAgICAgeyBuYW1lOiAnZGlzdG9ydCcsIGRlZmF1bHRWYWx1ZTogMCB9LAogICAgICB7IG5hbWU6ICdwb3N0Z2FpbicsIGRlZmF1bHRWYWx1ZTogMSB9LAogICAgXTsKICB9CgogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuc3RhcnRlZCA9IGZhbHNlOwogIH0KCiAgcHJvY2VzcyhpbnB1dHMsIG91dHB1dHMsIHBhcmFtZXRlcnMpIHsKICAgIGNvbnN0IGlucHV0ID0gaW5wdXRzWzBdOwogICAgY29uc3Qgb3V0cHV0ID0gb3V0cHV0c1swXTsKCiAgICBjb25zdCBoYXNJbnB1dCA9ICEoaW5wdXRbMF0gPT09IHVuZGVmaW5lZCk7CiAgICBpZiAodGhpcy5zdGFydGVkICYmICFoYXNJbnB1dCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICB0aGlzLnN0YXJ0ZWQgPSBoYXNJbnB1dDsKCiAgICBjb25zdCBzaGFwZSA9IE1hdGguZXhwbTEocGFyYW1ldGVycy5kaXN0b3J0WzBdKTsKICAgIGNvbnN0IHBvc3RnYWluID0gTWF0aC5tYXgoMC4wMDEsIE1hdGgubWluKDEsIHBhcmFtZXRlcnMucG9zdGdhaW5bMF0pKTsKCiAgICBmb3IgKGxldCBuID0gMDsgbiA8IGJsb2NrU2l6ZTsgbisrKSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXQubGVuZ3RoOyBpKyspIHsKICAgICAgICBvdXRwdXRbaV1bbl0gPSAoKCgxICsgc2hhcGUpICogaW5wdXRbaV1bbl0pIC8gKDEgKyBzaGFwZSAqIE1hdGguYWJzKGlucHV0W2ldW25dKSkpICogcG9zdGdhaW47CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KfQpyZWdpc3RlclByb2Nlc3NvcignZGlzdG9ydC1wcm9jZXNzb3InLCBEaXN0b3J0UHJvY2Vzc29yKTsKCi8vIFNVUEVSU0FXCmZ1bmN0aW9uIGxlcnAoYSwgYiwgbikgewogIHJldHVybiBuICogKGIgLSBhKSArIGE7Cn0KCmZ1bmN0aW9uIGdldFVuaXNvbkRldHVuZSh1bmlzb24sIGRldHVuZSwgdm9pY2VJbmRleCkgewogIGlmICh1bmlzb24gPCAyKSB7CiAgICByZXR1cm4gMDsKICB9CiAgcmV0dXJuIGxlcnAoLWRldHVuZSAqIDAuNSwgZGV0dW5lICogMC41LCB2b2ljZUluZGV4IC8gKHVuaXNvbiAtIDEpKTsKfQpjbGFzcyBTdXBlclNhd09zY2lsbGF0b3JQcm9jZXNzb3IgZXh0ZW5kcyBBdWRpb1dvcmtsZXRQcm9jZXNzb3IgewogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoKTsKICAgIHRoaXMucGhhc2UgPSBbXTsKICB9CiAgc3RhdGljIGdldCBwYXJhbWV0ZXJEZXNjcmlwdG9ycygpIHsKICAgIHJldHVybiBbCiAgICAgIHsKICAgICAgICBuYW1lOiAnYmVnaW4nLAogICAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgICBtYXg6IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSwKICAgICAgICBtaW46IDAsCiAgICAgIH0sCgogICAgICB7CiAgICAgICAgbmFtZTogJ2VuZCcsCiAgICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICAgIG1heDogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZLAogICAgICAgIG1pbjogMCwKICAgICAgfSwKCiAgICAgIHsKICAgICAgICBuYW1lOiAnZnJlcXVlbmN5JywKICAgICAgICBkZWZhdWx0VmFsdWU6IDQ0MCwKICAgICAgICBtaW46IE51bWJlci5FUFNJTE9OLAogICAgICB9LAoKICAgICAgewogICAgICAgIG5hbWU6ICdwYW5zcHJlYWQnLAogICAgICAgIGRlZmF1bHRWYWx1ZTogMC40LAogICAgICAgIG1pbjogMCwKICAgICAgICBtYXg6IDEsCiAgICAgIH0sCiAgICAgIHsKICAgICAgICBuYW1lOiAnZnJlcXNwcmVhZCcsCiAgICAgICAgZGVmYXVsdFZhbHVlOiAwLjIsCiAgICAgICAgbWluOiAwLAogICAgICB9LAogICAgICB7CiAgICAgICAgbmFtZTogJ2RldHVuZScsCiAgICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICAgIG1pbjogMCwKICAgICAgfSwKCiAgICAgIHsKICAgICAgICBuYW1lOiAndm9pY2VzJywKICAgICAgICBkZWZhdWx0VmFsdWU6IDUsCiAgICAgICAgbWluOiAxLAogICAgICB9LAogICAgXTsKICB9CiAgcHJvY2VzcyhpbnB1dCwgb3V0cHV0cywgcGFyYW1zKSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWYKICAgIGlmIChjdXJyZW50VGltZSA8PSBwYXJhbXMuYmVnaW5bMF0pIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWYKICAgIGlmIChjdXJyZW50VGltZSA+PSBwYXJhbXMuZW5kWzBdKSB7CiAgICAgIC8vIHRoaXMucG9ydC5wb3N0TWVzc2FnZSh7IHR5cGU6ICdvbmVuZGVkJyB9KTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgbGV0IGZyZXF1ZW5jeSA9IHBhcmFtcy5mcmVxdWVuY3lbMF07CiAgICAvL2FwcGx5IGRldHVuZSBpbiBjZW50cwogICAgZnJlcXVlbmN5ID0gZnJlcXVlbmN5ICogTWF0aC5wb3coMiwgcGFyYW1zLmRldHVuZVswXSAvIDEyMDApOwoKICAgIGNvbnN0IG91dHB1dCA9IG91dHB1dHNbMF07CiAgICBjb25zdCB2b2ljZXMgPSBwYXJhbXMudm9pY2VzWzBdOwogICAgY29uc3QgZnJlcXNwcmVhZCA9IHBhcmFtcy5mcmVxc3ByZWFkWzBdOwogICAgY29uc3QgcGFuc3ByZWFkID0gcGFyYW1zLnBhbnNwcmVhZFswXSAqIDAuNSArIDAuNTsKICAgIGNvbnN0IGdhaW4xID0gTWF0aC5zcXJ0KDEgLSBwYW5zcHJlYWQpOwogICAgY29uc3QgZ2FpbjIgPSBNYXRoLnNxcnQocGFuc3ByZWFkKTsKCiAgICBmb3IgKGxldCBuID0gMDsgbiA8IHZvaWNlczsgbisrKSB7CiAgICAgIGNvbnN0IGlzT2RkID0gKG4gJiAxKSA9PSAxOwoKICAgICAgLy9hcHBsaWVzIHVuaXNvbiAic3ByZWFkIiBkZXR1bmUgaW4gc2VtaXRvbmVzCiAgICAgIGNvbnN0IGZyZXEgPSBmcmVxdWVuY3kgKiBNYXRoLnBvdygyLCBnZXRVbmlzb25EZXR1bmUodm9pY2VzLCBmcmVxc3ByZWFkLCBuKSAvIDEyKTsKICAgICAgbGV0IGdhaW5MID0gZ2FpbjE7CiAgICAgIGxldCBnYWluUiA9IGdhaW4yOwogICAgICAvLyBpbnZlcnQgcmlnaHQgYW5kIGxlZnQgZ2FpbgogICAgICBpZiAoaXNPZGQpIHsKICAgICAgICBnYWluTCA9IGdhaW4yOwogICAgICAgIGdhaW5SID0gZ2FpbjE7CiAgICAgIH0KICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVmCiAgICAgIGNvbnN0IGR0ID0gZnJlcSAvIHNhbXBsZVJhdGU7CgogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dFswXS5sZW5ndGg7IGkrKykgewogICAgICAgIHRoaXMucGhhc2Vbbl0gPSB0aGlzLnBoYXNlW25dID8/IE1hdGgucmFuZG9tKCk7CiAgICAgICAgY29uc3QgdiA9IHdhdmVzaGFwZXMuc2F3YmxlcCh0aGlzLnBoYXNlW25dLCBkdCk7CgogICAgICAgIG91dHB1dFswXVtpXSA9IG91dHB1dFswXVtpXSArIHYgKiBnYWluTDsKICAgICAgICBvdXRwdXRbMV1baV0gPSBvdXRwdXRbMV1baV0gKyB2ICogZ2FpblI7CgogICAgICAgIHRoaXMucGhhc2Vbbl0gKz0gZHQ7CgogICAgICAgIGlmICh0aGlzLnBoYXNlW25dID4gMS4wKSB7CiAgICAgICAgICB0aGlzLnBoYXNlW25dID0gdGhpcy5waGFzZVtuXSAtIDE7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KCnJlZ2lzdGVyUHJvY2Vzc29yKCdzdXBlcnNhdy1vc2NpbGxhdG9yJywgU3VwZXJTYXdPc2NpbGxhdG9yUHJvY2Vzc29yKTsK";
function Q(e) {
const n = m().createGain();
return n.gain.value = e, n;
}
const Qe = (e, n, t, o) => o - t === 0 ? 0 : (n - e) / (o - t);
function E(e, n, t, o) {
const c = new AudioWorkletNode(e, n, o);
return Object.entries(t).forEach(([g, s]) => {
c.parameters.get(g).value = s;
}), c;
}
const U = (e, n, t, o, c, g, s, a, I, i = "exponential") => {
n = J(n), t = J(t), o = J(o), c = J(c);
const r = i === "exponential" ? "exponentialRampToValueAtTime" : "linearRampToValueAtTime";
i === "exponential" && (g = g === 0 ? 1e-3 : g, s = s === 0 ? 1e-3 : s);
const d = s - g, l = s, C = g + o * d, u = I - a, A = (h) => {
let b;
if (n > h) {
let f = Qe(g, l, 0, n);
b = h * f + (g > l ? g : 0);
} else
b = (h - n) * Qe(l, C, 0, t) + l;
return i === "exponential" && (b = b || 1e-3), b;
};
e.setValueAtTime(g, a), n > u ? e[r](A(u), I) : n + t > u ? (e[r](A(n), a + n), e[r](A(u), I)) : (e[r](A(n), a + n), e[r](A(n + t), a + n + t), e.setValueAtTime(C, I)), e[r](g, I + c);
};
function Sn(e, n, t, o, c, g) {
const s = {
threshold: n ?? -3,
ratio: t ?? 10,
knee: o ?? 10,
attack: c ?? 5e-3,
release: g ?? 0.05
};
return new DynamicsCompressorNode(e, s);
}
const q = (e, n = "linear", t) => {
const [s, a, I, i] = e;
if (s == null && a == null && I == null && i == null)
return t ?? [1e-3, 1e-3, 1, 0.01];
const r = I ?? (s != null && a == null || s == null && a == null ? 1 : 1e-3);
return [Math.max(s ?? 0, 1e-3), Math.max(a ?? 0, 1e-3), Math.min(r, 1), Math.max(i ?? 0, 0.01)];
};
function Ce(e, n, t, o, c, g, s, a, I, i, r, d, l, C) {
const u = "exponential", [A, h, b, f] = q([c, g, s, a], u, [5e-3, 0.14, 0, 0.1]);
let Z, p;
if (l === "ladder" ? (Z = E(e, "ladder-processor", { frequency: t, q: o, drive: C }), p = Z.parameters.get("frequency")) : (Z = e.createBiquadFilter(), Z.type = n, Z.Q.value = o, Z.frequency.value = t, p = Z.frequency), (c ?? g ?? s ?? a ?? I) !== void 0) {
I = J(I, 1, !0), d = J(d, 0, !0);
const W = Math.abs(I), S = W * d;
let K = ne(2 ** -S * t, 0, 2e4), H = ne(2 ** (W - S) * t, 0, 2e4);
return I < 0 && ([K, H] = [H, K]), U(p, A, h, b, f, K, H, i, r, u), Z;
}
return Z;
}
let Ee = (e) => e < 0.5 ? 1 : 1 - (e - 0.5) / 0.5;
function Fn(e, n, t = 0) {
const o = m();
if (!t)
return e;
let c = o.createGain(), g = o.createGain();
e.connect(c), n.connect(g), c.gain.value = Ee(t), g.gain.value = Ee(1 - t);
let s = o.createGain();
return c.connect(s), g.connect(s), s;
}
let Rn = ["linear", "exponential"];
function Ge(e, n, t, o) {
if (!(n.pattack ?? n.pdecay ?? n.psustain ?? n.prelease ?? n.penv))
return;
const g = J(n.penv, 1, !0), s = Rn[n.pcurve ?? 0];
let [a, I, i, r] = q(
[n.pattack, n.pdecay, n.psustain, n.prelease],
s,
[0.2, 1e-3, 1, 1e-3]
), d = n.panchor ?? i;
const l = g * 100, C = 0 - l * d, u = l - l * d;
U(e, a, I, i, r, C, u, t, o, s);
}
function me(e, n, t) {
const { vibmod: o = 0.5, vib: c } = n;
let g;
if (c > 0) {
g = m().createOscillator(), g.frequency.value = c;
const s = m().createGain();
return s.gain.value = o * 100, g.connect(s), s.connect(e), g.start(t), g;
}
}
function zn(e, n, t, o) {
const c = e.createConstantSource();
c.start(t), c.stop(o), c.onended = () => {
n();
};
}
const Mn = (e, n = 1, t = "sine") => {
const o = m(), c = o.createOscillator();
c.type = t, c.frequency.value = e, c.start();
const g = new GainNode(o, { gain: n });
return c.connect(g), { node: g, stop: (s) => c.stop(s) };
}, vn = (e, n, t, o = "sine") => {
const g = e.value * n, s = g * t;
return Mn(g, s, o);
};
function $e(e, n, t) {
const {
fmh: o = 1,
fmi: c,
fmenv: g = "exp",
fmattack: s,
fmdecay: a,
fmsustain: I,
fmrelease: i,
fmvelocity: r,
fmwave: d = "sine",
duration: l
} = n;
let C, u = () => {
};
if (c) {
const h = m().createGain(), b = vn(e, o, c, d);
if (C = b.node, u = b.stop, ![s, a, I, i, r].find((f) => f !== void 0))
C.connect(e);
else {
const [f, Z, p, y] = q([s, a, I, i]), W = t + l;
U(
h.gain,
f,
Z,
p,
y,
0,
1,
t,
W,
g === "exp" ? "exponential" : "linear"
), C.connect(h), h.connect(e);
}
}
return { stop: u };
}
const pe = {}, de = {}, ut = (e) => pe[e];
function Dn(e, n) {
var t = n ? 1e3 : 1024;
if (e < t)
return e + " B";
var o = n ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"], c = -1;
do
e /= t, ++c;
while (e >= t);
return e.toFixed(1) + " " + o[c];
}
const Jn = async (e, n, t, o, c, g, s) => {
let a = 0;
c !== void 0 && t !== void 0 && v("[sampler] hap has note and freq. ignoring note", "warning");
let I = Kn({ freq: c, note: t }, 36);
a = I - 36;
const i = m();
let r, d = 0;
if (Array.isArray(g))
d = je(n, g.length), r = g[d];
else {
const A = (b) => ie(b) - I, h = Object.keys(g).filter((b) => !b.startsWith("_")).reduce(
(b, f, Z) => !b || Math.abs(A(f)) < Math.abs(A(b)) ? f : b,
null
);
a = -A(h), d = je(n, g[h].length), r = g[h][d];
}
s && (r = await s(r));
let l = await en(r, i, e, d);
o < 0 && (l = kn(l));
const C = i.createBufferSource();
C.buffer = l;
const u = 1 * Math.pow(2, a / 12);
return C.playbackRate.value = u, C;
}, en = (e, n, t, o = 0) => {
const c = t ? `sound "${t}:${o}"` : "sample";
if (e = e.replace("#", "%23"), !de[e]) {
v(`[sampler] load ${c}..`, "load-sample", { url: e });
const g = Date.now();
de[e] = fetch(e).then((s) => s.arrayBuffer()).then(async (s) => {
const a = Date.now() - g, I = Dn(s.byteLength);
v(`[sampler] load ${c}... done! loaded ${I} in ${a}ms`, "loaded-sample", { url: e });
const i = await n.decodeAudioData(s);
return pe[e] = i, i;
});
}
return de[e];
};
function kn(e) {
const n = m(), t = n.createBuffer(e.numberOfChannels, e.length, n.sampleRate);
for (let o = 0; o < e.numberOfChannels; o++)
t.copyToChannel(e.getChannelData(o).slice().reverse(), o, o);
return t;
}
const At = (e) => pe[e];
function nn(e) {
if (e.startsWith("bubo:")) {
const [n, t] = e.split(":");
e = `github:Bubobubobubobubo/dough-${t}`;
}
return e;
}
function tn(e, n = "") {
if (!e.startsWith("github:"))
throw new Error('expected "github:" at the start of pseudoUrl');
let [t, o] = e.split("github:");
return o = o.endsWith("/") ? o.slice(0, -1) : o, o.split("/").length === 2 && (o += "/main"), `https://raw.githubusercontent.com/${o}/${n}`;
}
const Tn = (e, n, t = e._base || "") => Object.entries(e).forEach(([o, c]) => {
if (typeof c == "string" && (c = [c]), typeof c != "object")
throw new Error("wrong sample map format for " + o);
t = c._base || t, t = nn(t), t.startsWith("github:") && (t = tn(t, ""));
const g = (s) => t + s;
Array.isArray(c) ? c = c.map(g) : c = Object.fromEntries(
Object.entries(c).map(([s, a]) => [s, (typeof a == "string" ? [a] : a).map(g)])
), n(o, c);
});
let on = {};
function ht(e, n) {
on[e] = n;
}
function Ln(e) {
const n = Object.entries(on).find(([t]) => e.startsWith(t));
if (n)
return n[1];
}
const xn = async (e, n = e._base || "", t = {}) => {
if (typeof e == "string") {
const g = Ln(e);
if (g)
return g(e);
if (e = nn(e), e.startsWith("github:") && (e = tn(e, "strudel.json")), e.startsWith("local:") && (e = "http://localhost:5432"), e.startsWith("shabda:")) {
let [a, I] = e.split("shabda:");
e = `https://shabda.ndre.gr/${I}.json?strudel=1`;
}
if (e.startsWith("shabda/speech")) {
let [a, I] = e.split("shabda/speech");
I = I.startsWith("/") ? I.substring(1) : I;
let [i, r] = I.split(":"), d = "f", l = "en-GB";
i && ([l, d] = i.split("/")), e = `https://shabda.ndre.gr/speech/${r}.json?gender=${d}&language=${l}&strudel=1'`;
}
if (typeof fetch != "function")
return;
const s = e.split("/").slice(0, -1).join("/");
return typeof fetch > "u" ? void 0 : fetch(e).then((a) => a.json()).then((a) => xn(a, n || a._base || s, t)).catch((a) => {
throw console.error(a), new Error(`error loading "${e}"`);
});
}
const { prebake: o, tag: c } = t;
Tn(
e,
(g, s) => oe(g, (a, I, i) => On(a, I, i, s), {
type: "sample",
samples: s,
baseUrl: n,
prebake: o,
tag: c
}),
n
);
}, Ue = [];
async function On(e, n, t, o, c) {
let {
s: g,
freq: s,
unit: a,
nudge: I = 0,
// TODO: is this in seconds?
cut: i,
loop: r,
clip: d = void 0,
// if set, samples will be cut off when the hap ends
n: l = 0,
note: C,
speed: u = 1,
// sample playback speed
loopBegin: A = 0,
begin: h = 0,
loopEnd: b = 1,
end: f = 1,
duration: Z
} = n;
if (u === 0)
return;
r = g.startsWith("wt_") ? 1 : n.loop;
const p = m();
let [y, W, S, K] = q([n.attack, n.decay, n.sustain, n.release]);
const H = e + I, B = await Jn(g, l, C, u, s, o, c);
let D = me(B.detune, n, e);
if (p.currentTime > e) {
v(`[sampler] still loading sound "${g}:${l}"`, "highlight");
return;
}
if (!B) {
v(`[sampler] could not load "${g}:${l}"`, "error");
return;
}
B.playbackRate.value = Math.abs(u) * B.playbackRate.value, a === "c" && (B.playbackRate.value = B.playbackRate.value * B.buffer.duration * 1);
const X = h * B.buffer.duration;
r && (B.loop = !0, B.loopStart = A * B.buffer.duration - X, B.loopEnd = b * B.buffer.duration - X), B.start(H, X);
const Y = p.createGain(), L = B.connect(Y);
if (d == null && r == null && n.release == null) {
const k = B.buffer.duration / B.playbackRate.value;
Z = (f - h) * k;
}
let x = e + Z;
U(L.gain, y, W, S, K, 0, 1, e, x, "linear"), Ge(B.detune, n, e, x);
const N = p.createGain();
L.connect(N), B.onended = function() {
B.disconnect(), D?.stop(), L.disconnect(), N.disconnect(), t();
};
let F = x + K + 0.01;
B.stop(F);
const O = { node: N, bufferSource: B, stop: (k, we) => {
} };
if (i !== void 0) {
const k = Ue[i];
k && (k.node.gain.setValueAtTime(1, H), k.node.gain.linearRampToValueAtTime(0, H + 0.01)), Ue[i] = O;
}
return O;
}
const Ze = Zn();
function oe(e, n, t = {}) {
Ze.setKey(e, { onTrigger: n, data: t });
}
function ue(e) {
return Ze.get()[e];
}
const gn = {
s: "triangle",
gain: 0.8,
postgain: 1,
density: ".03",
ftype: "12db",
fanchor: 0,
resonance: 1,
hresonance: 1,
bandq: 1,
channels: [1, 2],
phaserdepth: 0.75,
shapevol: 1,
distortvol: 1,
delay: 0,
delayfeedback: 0.5,
delaytime: 0.25,
orbit: 1,
i: 1,
velocity: 1,
fft: 8
};
let ye = new Map(Object.entries(gn));
function cn(e, n) {
ye.set(e, n);
}
function V(e) {
return ye.get(e);
}
function bt(e) {
Object.keys(e).forEach((n) => {
cn(n, e[n]);
});
}
function jn() {
ye = new Map(Object.entries(gn));
}
function Bt(e) {
jn(), e === "1.0" && cn("fanchor", 0.5);
}
const ft = () => Ze.set({});
let ae;
const Qn = () => (ae = new AudioContext(), ae), m = () => ae || Qn();
let Ae;
function En() {
return Ae || (Ae = m().audioWorklet.addModule(Yn)), Ae;
}
async function Un(e = {}) {
const { disableWorklets: n = !1 } = e;
if (!(typeof window > "u")) {
if (await m().resume(), n) {
v("[superdough]: AudioWorklets disabled with disableWorklets");
return;
}
try {
await En(), v("[superdough] AudioWorklets loaded");
} catch (t) {
console.warn("could not load AudioWorklet effects", t);
}
v("[superdough] ready");
}
}
let he;
async function Gt(e) {
return he || (he = new Promise((n) => {
document.addEventListener("click", async function t() {
document.removeEventListener("click", t), await Un(e), n();
});
})), he;
}
let T = {}, Ie, _;
function qn() {
const e = m(), n = e.destination.maxChannelCount;
e.destination.channelCount = n, Ie = new ChannelMergerNode(e, { numberOfInputs: e.destination.channelCount }), _ = new GainNode(e), Ie.connect(_), _.connect(e.destination);
}
const Xe = (e, n = [0, 1]) => {
const t = m();
Ie == null && qn();
const o = new StereoPannerNode(t);
e.connect(o);
const c = new ChannelSplitterNode(t, {
numberOfOutputs: o.channelCount
});
o.connect(c), n.forEach((g, s) => {
c.connect(Ie, s % o.channelCount, ne(g, 0, t.destination.channelCount - 1));
});
}, mt = () => {
_ != null && (_.gain.linearRampToValueAtTime(0, m().currentTime + 0.01), _ = null);
};
function Pn(e, n, t, o) {
if (t = ne(t, 0, 0.98), !T[e]) {
const g = m().createFeedbackDelay(1, n, t);
g.start?.(o), Xe(g, [0, 1]), T[e] = g;
}
return T[e].delayTime.value !== n && T[e].delayTime.setValueAtTime(n, o), T[e].feedback.value !== t && T[e].feedback.setValueAtTime(t, o), T[e];
}
function _n(e, n, t = 1, o = 0.5, c = 1e3, g = 2e3) {
const s = m(), a = s.createGain();
a.gain.value = g * 2, E(s, "lfo-processor", {
frequency: t,
depth: 1,
skew: 0,
phaseoffset: 0,
time: e,
end: n,
shape: 1,
dcoffset: -0.5
}).connect(a);
const i = 2;
let r = 0;
const d = [];
for (let l = 0; l < i; l++) {
const C = s.createBiquadFilter();
C.type = "notch", C.gain.value = 1, C.frequency.value = c + r, C.Q.value = 2 - Math.min(Math.max(o * 2, 0), 1.9), a.connect(C.detune), r += 282, l > 0 && d[l - 1].connect(C), d.push(C);
}
return d[d.length - 1];
}
function $n(e) {
e = e ?? 0;
const n = ["12db", "ladder", "24db"];
return typeof e == "number" ? n[Math.floor(_e(e, n.length))] : e;
}
let z = {}, se = (e, n) => e !== void 0 && e !== n;
function et(e, n, t, o, c, g) {
if (!z[e]) {
const a = m().createReverb(n, t, o, c, g);
Xe(a, [0, 1]), z[e] = a;
}
return (se(n, z[e].duration) || se(t, z[e].fade) || se(o, z[e].lp) || se(c, z[e].dim) || z[e].ir !== g) && z[e].generate(n, t, o, c, g), z[e];
}
let M = {}, $ = {};
function nt(e, n = 1024) {
if (!M[e]) {
const t = m().createAnalyser();
t.fftSize = n, M[e] = t, $[e] = new Float32Array(M[e].frequencyBinCount);
}
return M[e].fftSize !== n && (M[e].fftSize = n, $[e] = new Float32Array(M[e].frequencyBinCount)), M[e];
}
function pt(e = "time", n = 1) {
const t = {
time: () => M[n]?.getFloatTimeDomainData($[n]),
frequency: () => M[n]?.getFloatFrequencyData($[n])
}[e];
if (!t)
throw new Error(`getAnalyzerData: ${e} not supported. use one of ${Object.keys(t).join(", ")}`);
return t(), $[n];
}
function be(e, n, t) {
const o = Q(t);
return e.connect(o), o.connect(n), o;
}
function Zt() {
T = {}, z = {}, M = {}, $ = {};
}
const tt = async (e, n, t) => {
const o = m();
if (typeof e != "object")
throw new Error(
`expected hap.value to be an object, but got "${e}". Hint: append .note() or .s() to the end`,
"error"
);
if (e.duration = t, n = typeof n == "string" && n.startsWith("=") ? Number(n.slice(1)) : o.currentTime + n, n < o.currentTime) {
console.warn(
`[superdough]: cannot schedule sounds in the past (target: ${n.toFixed(2)}, now: ${o.currentTime.toFixed(2)})`
);
return;
}
let {
s: c = V("s"),
bank: g,
source: s,
gain: a = V("gain"),
postgain: I = V("postgain"),
density: i = V("density"),
// filters
fanchor: r = V("fanchor"),
drive: d = 0.69,
// low pass
cutoff: l,
lpenv: C,
lpattack: u,
lpdecay: A,
lpsustain: h,
lprelease: b,
resonance: f = V("resonance"),
// high pass
hpenv: Z,
hcutoff: p,
hpattack: y,
hpdecay: W,
hpsustain: S,
hprelease: K,
hresonance: H = V("hresonance"),
// band pass
bpenv: B,
bandf: D,
bpattack: X,
bpdecay: Y,
bpsustain: L,
bprelease: x,
bandq: N = V("bandq"),
channels: F = V("channels"),
//phaser
phaser: R,
phaserdepth: O = V("phaserdepth"),
phasersweep: k,
phasercenter: we,
//
coarse: Ve,
crush: We,
shape: He,
shapevol: rn = V("shapevol"),
distort: Ne,
distortvol: ln = V("distortvol"),
pan: Ke,
vowel: Ye,
delay: Se = V("delay"),
delayfeedback: Fe = V("delayfeedback"),
delaytime: Re = V("delaytime"),
orbit: ze = V("orbit"),
room: Me,
roomfade: Cn,
roomlp: dn,
roomdim: un,
roomsize: An,
ir: re,
i: ve = V("i"),
velocity: hn = V("velocity"),
analyze: De,
// analyser wet
fft: bn = V("fft"),
// fftSize 0 - 10
compressor: Je,
compressorRatio: Bn,
compressorKnee: fn,
compressorAttack: Gn,
compressorRelease: mn
} = e;
a = J(a, 1), F = (Array.isArray(F) ? F : [F]).map((G) => G - 1), a *= hn;
let ke = [];
const pn = () => {
ke.forEach((G) => G?.disconnect());
};
g && c && (c = `${g}_${c}`);
let ge;
if (s)
ge = s(n, e, t);
else if (ue(c)) {
const { onTrigger: G } = ue(c), j = await G(n, e, pn);
j && (ge = j.node, j.stop(n + t));
} else
throw new Error(`sound ${c} not found! Is it loaded?`);
if (!ge)
return;
if (o.currentTime > n) {
v("[webaudio] skip hap: still loading", o.currentTime - n);
return;
}
const w = [];
w.push(ge), w.push(Q(a));
const ce = $n(e.ftype);
if (l !== void 0) {
let G = () => Ce(
o,
"lowpass",
l,
f,
u,
A,
h,
b,
C,
n,
n + t,
r,
ce,
d
);
w.push(G()), ce === "24db" && w.push(G());
}
if (p !== void 0) {
let G = () => Ce(
o,
"highpass",
p,
H,
y,
W,
S,
K,
Z,
n,
n + t,
r
);
w.push(G()), ce === "24db" && w.push(G());
}
if (D !== void 0) {
let G = () => Ce(
o,
"bandpass",
D,
N,
X,
Y,
L,
x,
B,
n,
n + t,
r
);
w.push(G()), ce === "24db" && w.push(G());
}
if (Ye !== void 0) {
const G = o.createVowelFilter(Ye);
w.push(G);
}
if (Ve !== void 0 && w.push(E(o, "coarse-processor", { coarse: Ve })), We !== void 0 && w.push(E(o, "crush-processor", { crush: We })), He !== void 0 && w.push(E(o, "shape-processor", { shape: He, postgain: rn })), Ne !== void 0 && w.push(E(o, "distort-processor", { distort: Ne, postgain: ln })), Je !== void 0 && w.push(
Sn(o, Je, Bn, fn, Gn, mn)
), Ke !== void 0) {
const G = o.createStereoPanner();
G.pan.value = 2 * Ke - 1, w.push(G);
}
if (R !== void 0 && O > 0) {
const G = _n(n, n + t, R, O, we, k);
w.push(G);
}
const te = new GainNode(o, { gain: I });
w.push(te), Xe(te, F);
let Te;
if (Se > 0 && Re > 0 && Fe > 0) {
const G = Pn(ze, Re, Fe, n);
Te = be(te, G, Se);
}
let Le;
if (Me > 0) {
let G;
if (re !== void 0) {
let le, P = ue(re);
Array.isArray(P) ? le = P.data.samples[ve % P.data.samples.length] : typeof P == "object" && (le = Object.values(P.data.samples).flat()[ve % Object.values(P.data.samples).length]), G = await en(le, o, re, 0);
}
const j = et(ze, An, Cn, dn, un, G);
Le = be(te, j, Me);
}
let xe;
if (De) {
const G = nt(De, 2 ** (bn + 5));
xe = be(te, G, 1);
}
w.slice(1).reduce((G, j) => G.connect(j), w[0]), ke = w.concat([Te, Le, xe]);
}, yt = (e, n, t, o) => tt(n, e - t, n.duration / o);
let Be = {};
function ot(e, n) {
const t = m();
if (Be[e])
return Be[e];
const o = 2 * t.sampleRate, c = t.createBuffer(1, o, t.sampleRate), g = c.getChannelData(0);
let s = 0, a, I, i, r, d, l, C;
a = I = i = r = d = l = C = 0;
for (let u = 0; u < o; u++)
if (e === "white")
g[u] = Math.random() * 2 - 1;
else if (e === "brown") {
let A = Math.random() * 2 - 1;
g[u] = (s + 0.02 * A) / 1.02, s = g[u];
} else if (e === "pink") {
let A = Math.random() * 2 - 1;
a = 0.99886 * a + A * 0.0555179, I = 0.99332 * I + A * 0.0750759, i = 0.969 * i + A * 0.153852, r = 0.8665 * r + A * 0.3104856, d = 0.55 * d + A * 0.5329522, l = -0.7616 * l - A * 0.016898, g[u] = a + I + i + r + d + l + C + A * 0.5362, g[u] *= 0.11, C = A * 0.115926;
} else if (e === "crackle") {
const A = n * 0.01;
Math.random() < A ? g[u] = Math.random() * 2 - 1 : g[u] = 0;
}
return e !== "crackle" && (Be[e] = c), c;
}
function sn(e = "white", n, t = 0.02) {
const c = m().createBufferSource();
return c.buffer = ot(e, t), c.loop = !0, c.start(n), {
node: c,
stop: (g) => c.stop(g)
};
}
function gt(e, n, t) {
const o = sn("pink", t);
return {
node: Fn(e, o.node, n),
stop: (g) => o?.stop(g)
};
}
const an = (e) => {
let { note: n, freq: t } = e;
return n = n || 36, typeof n == "string" && (n = ie(n)), !t && typeof n == "number" && (t = Pe(n)), Number(t);
}, ct = ["triangle", "square", "sawtooth", "sine"], st = ["pink", "white", "brown", "crackle"];
function Xt() {
[...ct].forEach((e) => {
oe(
e,
(n, t, o) => {
const [c, g, s, a] = q(
[t.attack, t.decay, t.sustain, t.release],
"linear",
[1e-3, 0.05, 0.6, 0.01]
);
let I = It(e, n, t), { node: i, stop: r, triggerRelease: d } = I;
const l = Q(0.3), { duration: C } = t;
i.onended = () => {
i.disconnect(), l.disconnect(), o();
};
const u = Q(1);
let A = i.connect(l).connect(u);
const h = n + C;
U(A.gain, c, g, s, a, 0, 1, n, h, "linear");
const b = h + a + 0.01;
return d?.(b), r(b), {
node: A,
stop: (f) => {
}
};
},
{ type: "synth", prebake: !0 }
);
}), oe(
"supersaw",
(e, n, t) => {
const o = m();
let { duration: c, n: g, unison: s = 5, spread: a = 0.6, detune: I } = n;
I = I ?? g ?? 0.18;
const i = an(n), [r, d, l, C] = q(
[n.attack, n.decay, n.sustain, n.release],
"linear",
[1e-3, 0.05, 0.6, 0.01]
), u = e + c, A = u + C + 0.01, h = ne(s, 1, 100);
let b = h > 1 ? ne(a, 0, 1) : 0, f = E(
o,
"supersaw-oscillator",
{
frequency: i,
begin: e,
end: A,
freqspread: I,
voices: h,
panspread: b
},
{
outputChannelCount: [2]
}
);
const Z = 1 / Math.sqrt(h);
Ge(f.parameters.get("detune"), n, e, u);
const p = me(f.parameters.get("detune"), n, e), y = $e(f.parameters.get("frequency"), n, e);
let W = Q(1);
return W = f.connect(W), zn(
o,
() => {
f.disconnect(), W.disconnect(), t(), y?.stop(), p?.stop();
},
e,
A
), U(W.gain, r, d, l, C, 0, 0.3 * Z, e, u, "linear"), {
node: W,
stop: (S) => {
}
};
},
{ prebake: !0, type: "synth" }
), [...st].forEach((e) => {
oe(
e,
(n, t, o) => {
const [c, g, s, a] = q(
[t.attack, t.decay, t.sustain, t.release],
"linear",
[1e-3, 0.05, 0.6, 0.01]
);
let I, { density: i } = t;
I = sn(e, n, i);
let { node: r, stop: d, triggerRelease: l } = I;
const C = Q(0.3), { duration: u } = t;
r.onended = () => {
r.disconnect(), C.disconnect(), o();
};
const A = Q(1);
let h = r.connect(C).connect(A);
const b = n + u;
U(h.gain, c, g, s, a, 0, 1, n, b, "linear");
const f = b + a + 0.01;
return l?.(f), d(f), {
node: h,
stop: (Z) => {
}
};
},
{ type: "synth", prebake: !0 }
);
});
}
function at(e, n) {
const t = new Float32Array(e + 1), o = new Float32Array(e + 1), c = m(), g = c.createOscillator(), s = {
sawtooth: (i) => [0, -1 / i],
square: (i) => [0, i % 2 === 0 ? 0 : 1 / i],
triangle: (i) => [i % 2 === 0 ? 0 : 1 / (i * i), 0]
};
if (!s[n])
throw new Error(`unknown wave type ${n}`);
t[0] = 0, o[0] = 0;
let a = 1;
for (; a <= e; ) {
const [i, r] = s[n](a);
t[a] = i, o[a] = r, a++;
}
const I = c.createPeriodicWave(t, o);
return g.setPeriodicWave(I), g;
}
function It(e, n, t) {
let { n: o, duration: c, noise: g = 0 } = t, s;
!o || e === "sine" ? (s = m().createOscillator(), s.type = e || "triangle") : s = at(o, e), s.frequency.value = an(t), s.start(n);
let a = me(s.detune, t, n);
Ge(s.detune, t, n, n + c);
const I = $e(s.frequency, t, n);
let i;
return g && (i = gt(s, g, n)), {
node: i?.node || s,
stop: (r) => {
I.stop(r), a?.stop(r), i?.stop(r), s.stop(r);
},
triggerRelease: (r) => {
}
};
}
function it(e = 1, n = 0.05, t = 220, o = 0, c = 0, g = 0.1, s = 0, a = 1, I = 0, i = 0, r = 0, d = 0, l = 0, C = 0, u = 0, A = 0, h = 0, b = 1, f = 0, Z = 0) {
let p = Math.PI * 2, y = m().sampleRate, W = (O) => O > 0 ? 1 : -1, S = I *= 500 * p / y / y, K = t *= (1 + n * 2 * Math.random() - n) * p / y, H = [], B = 0, D = 0, X = 0, Y = 1, L = 0, x = 0, N = 0, F, R;
for (o = o * y + 9, f *= y, c *= y, g *= y, h *= y, i *= 500 * p / y ** 3, u *= p / y, r *= p / y, d *= y, l = l * y | 0, R = o + f + c + g + h | 0; X < R; H[X++] = N)
++x % (A * 100 | 0) || (N = s ? s > 1 ? s > 2 ? s > 3 ? Math.sin((B % p) ** 3) : Math.max(Math.min(Math.tan(B), 1), -1) : 1 - (2 * B / p % 2 + 2) % 2 : 1 - 4 * Math.abs(Math.round(B / p) - B / p) : Math.sin(B), N = (l ? 1 - Z + Z * Math.sin(p * X / l) : 1) * W(N) * Math.abs(N) ** a * // curve 0=square, 2=pointy
e * 1 * // envelope
(X < o ? X / o : X < o + f ? 1 - (X - o) / f * (1 - b) : X < o + f + c ? b : X < R - h ? (R - X - h) / g * // release falloff
b : 0), N = h ? N / 2 + (h > X ? 0 : (X < R - h ? 1 : (R - X) / h) * // release delay
H[X - h | 0] / 2) : N), F = (t += I += i) * // frequency
Math.cos(u * D++), B += F - F * C * (1 - (Math.sin(X) + 1) * 1e9 % 2), Y && ++Y > d && (t += r, K += r, Y = 0), l && !(++L % l) && (t = K, I = S, Y ||= 1);
return H;
}
const rt = (e, n) => {
let {
s: t,
note: o = 36,
freq: c,
//
zrand: g = 0,
attack: s = 0,
decay: a = 0,
sustain: I = 0.8,
release: i = 0.1,
curve: r = 1,
slide: d = 0,
deltaSlide: l = 0,
pitchJump: C = 0,
pitchJumpTime: u = 0,
lfo: A = 0,
znoise: h = 0,
zmod: b = 0