1951 lines
79 KiB
JavaScript
1951 lines
79 KiB
JavaScript
function W(e, a) {
|
|
if (a || (a = "assertion failed"), !e)
|
|
throw new Error(a);
|
|
}
|
|
class c {
|
|
constructor(a, n) {
|
|
this.type = a, n !== void 0 && (this.value = n), this.ins = [];
|
|
}
|
|
static parseInput(a, n) {
|
|
if (typeof a == "function") {
|
|
if (!n)
|
|
throw new Error(
|
|
"tried to parse function input without without passing node.."
|
|
);
|
|
return a(n);
|
|
}
|
|
return typeof a == "object" ? a : typeof a == "number" && !isNaN(a) || typeof a == "string" ? X(a) : (console.log(
|
|
`invalid input type "${typeof a}" for node of type "${n.type}", falling back to 0. The input was:`,
|
|
a
|
|
), 0);
|
|
}
|
|
}
|
|
const x = (e, a) => new c(e, a);
|
|
let g = /* @__PURE__ */ new Map();
|
|
const Z = "poly", Y = "exit";
|
|
c.prototype.inherit = function(e) {
|
|
return e.inputOf && (this.inputOf = e.inputOf), e.outputOf && (this.outputOf = e.outputOf), this;
|
|
};
|
|
c.prototype.toObject = function() {
|
|
return JSON.parse(JSON.stringify(this));
|
|
};
|
|
c.prototype.stringify = function() {
|
|
return JSON.stringify(this, null, 2).replaceAll('"', "'");
|
|
};
|
|
function F(e, ...a) {
|
|
let n = 1;
|
|
if (a = a.map((s) => {
|
|
if (Array.isArray(s)) {
|
|
if (s.length === 1)
|
|
return s[0];
|
|
s = new c(Z).withIns(...s);
|
|
}
|
|
if (typeof s == "function") {
|
|
const o = s(new c("peek"));
|
|
o.type === Z && (n = Math.max(o.ins.length, n));
|
|
}
|
|
return s.type === Z && (n = Math.max(s.ins.length, n)), s;
|
|
}), n === 1) {
|
|
const s = x(e);
|
|
return s.withIns(...a.map((o) => c.parseInput(o, s)));
|
|
}
|
|
if (e === Y) {
|
|
const s = a.map((o) => o.type === Z ? o.ins.map((d) => c.parseInput(d).inherit(d)) : o).flat();
|
|
return x(Y).withIns(...s);
|
|
}
|
|
const t = Array.from({ length: n }, (s, o) => {
|
|
const d = new c(e), G = a.map((p) => p.type === Z ? c.parseInput(p.ins[o % p.ins.length], d).inherit(p) : (p = c.parseInput(p, d), p.type === Z && (p = p.ins[o]), p));
|
|
return d.withIns(...G);
|
|
});
|
|
return new c(Z).withIns(...t);
|
|
}
|
|
function oe(e, a) {
|
|
const n = g.get(e);
|
|
return n?.ins?.[a] ? n.ins[a].name : "";
|
|
}
|
|
let l = (e, a) => u(e, (...n) => F(e, ...n), a);
|
|
g.set("register", {
|
|
tags: ["meta"],
|
|
graph: !1,
|
|
description: "Registers a new Node function. Sets it on the prototype + returns the function itself. Like `module` but doesn't hide complexity in graph viz.",
|
|
examples: [
|
|
`let kick = register('kick', gate => gate.adsr(0,.11,0,.11)
|
|
.apply(env => env.mul(env)
|
|
.mul(158)
|
|
.sine(env)
|
|
.distort(.85)
|
|
))
|
|
impulse(2).kick().out()`
|
|
]
|
|
});
|
|
let u = (e, a, n) => (n && g.set(e, n), c.prototype[e] = function(...t) {
|
|
return a(this, ...t);
|
|
}, c.prototype["_" + e] = function() {
|
|
return this;
|
|
}, a);
|
|
g.set("module", {
|
|
tags: ["meta"],
|
|
graph: !0,
|
|
description: "Creates a module. Like `register`, but the graph viz will hide the internal complexity of the module.",
|
|
examples: [
|
|
`let kick = module('kick', gate => gate.adsr(0,.11,0,.11)
|
|
.apply(env => env.mul(env)
|
|
.mul(158)
|
|
.sine(env)
|
|
.distort(.85)
|
|
))
|
|
impulse(2).kick().out()`
|
|
]
|
|
});
|
|
let de = 0;
|
|
function y(e, a, n) {
|
|
return u(
|
|
e,
|
|
(...t) => {
|
|
const s = de++;
|
|
return t = t.map(
|
|
(o, d) => c.parseInput(o).asModuleInput?.(e, s, d)
|
|
), a(...t).asModuleOutput?.(e, s);
|
|
},
|
|
n
|
|
);
|
|
}
|
|
g.set("n", {
|
|
tags: ["math"],
|
|
description: "Constant value node. Turns a number into a Node.",
|
|
ins: [{ name: "value", default: 0 }]
|
|
});
|
|
function X(e) {
|
|
return Array.isArray(e) ? poly(...e.map((a) => X(a))) : typeof e == "object" ? e : x("n", e);
|
|
}
|
|
g.set("out", {
|
|
tags: ["meta"],
|
|
description: "Sends the node to the audio output"
|
|
});
|
|
g.set("withIns", {
|
|
internal: !0,
|
|
tags: ["innards"],
|
|
description: "Sets the inputs of a node. Returns the node itself",
|
|
ins: [{ name: "in", dynamic: !0 }]
|
|
});
|
|
c.prototype.withIns = function(...e) {
|
|
return this.ins = e, this;
|
|
};
|
|
g.set("flatten", {
|
|
internal: !0,
|
|
tags: ["innards"],
|
|
description: "Flattens the node to a list of all nodes in the graph, where each Node's ins are now indices"
|
|
});
|
|
c.prototype.flatten = function() {
|
|
return pe(this);
|
|
};
|
|
g.set("apply", {
|
|
graph: !0,
|
|
tags: ["meta"],
|
|
description: "Applies the given function to the Node. Useful when a node has to be used multiple times.",
|
|
examples: [
|
|
`impulse(4)
|
|
.apply(imp=>imp
|
|
.seq(110,220,330,440)
|
|
.sine()
|
|
.mul( imp.ad(.1,.1) )
|
|
).out()`
|
|
]
|
|
});
|
|
c.prototype.apply = function(e) {
|
|
return e(this);
|
|
};
|
|
g.set("clone", {
|
|
internal: !0,
|
|
tags: ["innards"],
|
|
description: "Clones the node"
|
|
});
|
|
c.prototype.clone = function() {
|
|
return new c(this.type, this.value).withIns(...this.ins);
|
|
};
|
|
g.set("map", {
|
|
tags: ["meta"],
|
|
description: "Applies the given function to all ins if it's poly node. Otherwise it applies the function to itself.",
|
|
examples: [
|
|
`n([110,220,330])
|
|
.map( freq=>freq.mul([1,1.007]).saw().mix() )
|
|
.mix(2).mul(.5).out()`
|
|
]
|
|
});
|
|
c.prototype.map = function(e) {
|
|
return this.type !== "poly" ? e(this) : poly(...this.ins.map(e));
|
|
};
|
|
c.prototype.channel = function(e) {
|
|
return this.type !== "poly" ? this : this.ins[e % this.ins.length];
|
|
};
|
|
g.set("select", {
|
|
tags: ["meta"],
|
|
graph: !0,
|
|
description: "Find the first occurence of the given type up in the graph and returns the match. Useful to exit a feedback loop at another point.",
|
|
examples: [
|
|
`sine(220).mul(impulse(1).ad(.001,.2))
|
|
.add( x=>x.delay(.2).mul(.8) )
|
|
.select('delay').out()
|
|
`
|
|
]
|
|
});
|
|
c.prototype.select = function(e) {
|
|
for (let a of this.ins) {
|
|
if (a.type === e)
|
|
return a;
|
|
const n = a.select(e);
|
|
if (n)
|
|
return n;
|
|
}
|
|
};
|
|
g.set("debug", {
|
|
tags: ["meta"],
|
|
description: "Logs the node to the console"
|
|
});
|
|
c.prototype.debug = function(e = (a) => a) {
|
|
return console.log(e(this)), this;
|
|
};
|
|
function ce(e) {
|
|
const a = modules.get(e), n = Array.from(
|
|
{ length: a.length },
|
|
(s, o) => x(`$INPUT${o}`)
|
|
), t = a(...n);
|
|
return JSON.stringify(t, null, 2);
|
|
}
|
|
function pe(e) {
|
|
const a = [];
|
|
return S(e, (n) => (a.push(n), n)), a.map((n) => {
|
|
let t = {
|
|
...n,
|
|
type: n.type,
|
|
ins: n.ins.map((s) => a.indexOf(s) + "")
|
|
};
|
|
return n.value !== void 0 && (t.value = n.value), n.to !== void 0 && (t.to = a.indexOf(n.to)), t;
|
|
});
|
|
}
|
|
let J = l("exit", { internal: !0 });
|
|
function j(e, a) {
|
|
let n = [];
|
|
const t = u("out", function(s, o = [0, 1]) {
|
|
return n.push(s.output(o)), s;
|
|
});
|
|
return a ? (a.out = t, Function(...Object.keys(a), e)(...Object.values(a))) : (globalThis.out = t, Function(e)()), J(...n);
|
|
}
|
|
c.prototype.over = function(e) {
|
|
return this.apply((a) => add(a, e(a)));
|
|
};
|
|
c.prototype.dfs = function(e, a) {
|
|
return this.apply((n) => S(n, e, a));
|
|
};
|
|
c.prototype.apply2 = function(e) {
|
|
return e(this, this);
|
|
};
|
|
let S = (e, a, n = []) => (e = a(e, n), n.push(e), e.ins = e.ins.map((t) => n.includes(t) ? t : S(t, a, n)), e);
|
|
c.prototype.asModuleInput = function(e, a, n) {
|
|
return this.inputOf = this.inputOf || [], this.inputOf.push([e, a, n]), this;
|
|
};
|
|
c.prototype.asModuleOutput = function(e, a) {
|
|
return this.outputOf = [e, a], this;
|
|
};
|
|
function T(e, a = {}) {
|
|
const {
|
|
log: n = !1,
|
|
lang: t = "js",
|
|
fallbackType: s = "thru",
|
|
constType: o = "n",
|
|
getRegister: d = (r) => `r[${r}]`,
|
|
getOutput: G = (r) => `o[${r}]`,
|
|
getSource: p = (r) => `s[${r}]`
|
|
} = a;
|
|
n && console.log("compile", e);
|
|
const h = ue(e);
|
|
let m = [], R = (r) => h[r].type !== o ? d(r) : typeof h[r].value == "string" ? `"${h[r].value}"` : h[r].value;
|
|
const f = [];
|
|
for (let r in h) {
|
|
const C = h[r], I = h[r].ins.map((le) => R(h.indexOf(le))), ie = f.length;
|
|
let b = g.get(C.type);
|
|
b || (console.warn(
|
|
`unhandled node type "${h[r].type}". falling back to "${s}"`
|
|
), b = g.get(s));
|
|
const se = {
|
|
vars: I,
|
|
node: C,
|
|
nodes: h,
|
|
id: r,
|
|
ugenIndex: ie,
|
|
ugen: b.ugen,
|
|
name: R(r),
|
|
lang: t,
|
|
getRegister: d,
|
|
getOutput: G,
|
|
getSource: p
|
|
};
|
|
b.compile && m.push(b.compile(se)), b.ugen && f.push({ type: b.ugen, inputs: I });
|
|
}
|
|
const z = m.join(`
|
|
`);
|
|
return n && (console.log("compiled code:"), console.log(z)), { src: z, ugens: f, registers: h.length };
|
|
}
|
|
c.prototype.compile = function(e) {
|
|
return T(this, e);
|
|
};
|
|
function ue(e) {
|
|
const a = [], n = /* @__PURE__ */ new Set();
|
|
function t(s) {
|
|
if (!(typeof s != "object" || n.has(s))) {
|
|
n.add(s);
|
|
for (let o in s.ins)
|
|
t(s.ins[o]);
|
|
a.push(s);
|
|
}
|
|
}
|
|
return t(e), a;
|
|
}
|
|
const U = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
__proto__: null,
|
|
compile: T
|
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
class Q {
|
|
constructor() {
|
|
this._events = {};
|
|
}
|
|
on(a, n) {
|
|
this._events[a] || (this._events[a] = []);
|
|
let t = this._events[a];
|
|
W(t.indexOf(n) == -1), t.push(n);
|
|
}
|
|
removeListener(a, n) {
|
|
let t = this._events[a], s = t.indexOf(n);
|
|
s != -1 && t.splice(s, 1);
|
|
}
|
|
trigger(a, ...n) {
|
|
let t = this._events[a] || [];
|
|
for (let s = 0; s < t.length; s++)
|
|
t[s].apply(null, n);
|
|
}
|
|
}
|
|
class me extends Q {
|
|
constructor(a = navigator) {
|
|
super(), this.midiAccess = null, this.getMIDIAccess(a);
|
|
}
|
|
// Try to get MIDI access from the browser
|
|
async getMIDIAccess(a) {
|
|
if ("requestMIDIAccess" in a) {
|
|
this.midiAccess = await a.requestMIDIAccess({ sysex: !1 }), console.log("got MIDI access");
|
|
for (let n of this.midiAccess.inputs.values())
|
|
n.state == "connected" && (n.onmidimessage = (t) => this.trigger("midimessage", n.id, t.data));
|
|
this.midiAccess.onstatechange = (n) => {
|
|
n.port.type == "input" && n.port.state == "connected" && (console.log(
|
|
"MIDI device connected:",
|
|
n.port.name,
|
|
"PORT:",
|
|
n.port.id
|
|
), n.port.onmidimessage = (t) => this.trigger("midimessage", n.port.id, t.data));
|
|
};
|
|
}
|
|
}
|
|
// Send a message to all MIDI devices
|
|
broadcast(a, n) {
|
|
if (midi)
|
|
for (let t of this.midiAccess.outputs.values())
|
|
t.send(a, n);
|
|
}
|
|
}
|
|
function re(e) {
|
|
let a = e[0] & 240, n = (e[0] & 15) + 1;
|
|
if (a == 176 && e.length == 3) {
|
|
let t = e[1], s = e[2] / 127 * 2 - 1;
|
|
return { type: "CC", channel: n, cc: t, value: s };
|
|
}
|
|
if (a == 224 && e.length == 3) {
|
|
let t = e[1], s = (e[2] << 7 | t) / 16383 * 2 - 1;
|
|
return { type: "PITCHBEND", channel: n, value: s };
|
|
}
|
|
if (a == 144 && e.length == 3) {
|
|
let t = e[1], s = e[2] / 127;
|
|
return { type: "NOTE_ON", channel: n, note: t, velocity: s };
|
|
}
|
|
if (a == 128 && e.length == 3) {
|
|
let t = e[1];
|
|
return { type: "NOTE_ON", channel: n, note: t, velocity: 0 };
|
|
}
|
|
}
|
|
class he extends Q {
|
|
constructor() {
|
|
super(), this.attach();
|
|
}
|
|
attach() {
|
|
typeof window < "u" && (this.handleMouseMove = (a) => {
|
|
const n = a.clientX / document.body.clientWidth * 2 - 1, t = a.clientY / document.body.clientHeight * 2 - 1;
|
|
this.trigger("move", n, t);
|
|
}, document.addEventListener("mousemove", this.handleMouseMove));
|
|
}
|
|
detach() {
|
|
typeof window < "u" && document.removeEventListener("mousemove", this.handleMouseMove);
|
|
}
|
|
}
|
|
const ge = "data:text/javascript;base64,KGZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIGcoaCx0KXtpZih0fHwodD0iYXNzZXJ0aW9uIGZhaWxlZCIpLCFoKXRocm93IG5ldyBFcnJvcih0KX1mdW5jdGlvbiBTKGgsdCxzKXtyZXR1cm4gaDw9MD90Omg+PTE/czp0K2gqKHMtdCl9ZnVuY3Rpb24gUChoLHQscyl7cmV0dXJuIGg8PXQ/MDpoPj1zPzE6cz09PXQ/MDooaC10KS8ocy10KX1mdW5jdGlvbiBFKGgsdCl7cmV0dXJuIGg8dD8oaC89dCxoK2gtaCpoLTEpOmg+MS10PyhoPShoLTEpL3QsaCpoK2graCsxKTowfWZ1bmN0aW9uIFUoaCl7cmV0dXJuIE1hdGguZmxvb3IoaCk9PT1ofWZ1bmN0aW9uIF8oaCl7cmV0dXJuIFUoaCkmJmg+MH1mdW5jdGlvbiBrKGgsdCl7dD1NYXRoLm1pbihNYXRoLm1heCh0LDApLDEpLHQtPS4wMTt2YXIgcz0yKnQvKDEtdCksZT0oMStzKSpoLygxK3MqTWF0aC5hYnMoaCkpO3JldHVybiBlfWZ1bmN0aW9uIHcoaCx0LHMpe3JldHVybiBoPj0xP3M6dCtoKihzLXQpfWZ1bmN0aW9uIFQoKXt0aGlzLnN0YXRlPSJvZmYiLHRoaXMuc3RhcnRUaW1lPTAsdGhpcy5zdGFydFZhbD0wfVQucHJvdG90eXBlLmV2YWw9ZnVuY3Rpb24oaCx0LHMsZSxpLG4pe3N3aXRjaCh0aGlzLnN0YXRlKXtjYXNlIm9mZiI6cmV0dXJuIHQ+MCYmKHRoaXMuc3RhdGU9ImF0dGFjayIsdGhpcy5zdGFydFRpbWU9aCx0aGlzLnN0YXJ0VmFsPTApLDA7Y2FzZSJhdHRhY2siOntsZXQgcj1oLXRoaXMuc3RhcnRUaW1lO3JldHVybiByPnM/KHRoaXMuc3RhdGU9ImRlY2F5Iix0aGlzLnN0YXJ0VGltZT1oLDEpOncoci9zLHRoaXMuc3RhcnRWYWwsMSl9Y2FzZSJkZWNheSI6e2xldCByPWgtdGhpcy5zdGFydFRpbWUsbD13KHIvZSwxLGkpO3JldHVybiB0PD0wPyh0aGlzLnN0YXRlPSJyZWxlYXNlIix0aGlzLnN0YXJ0VGltZT1oLHRoaXMuc3RhcnRWYWw9bCxsKTpyPmU/KHRoaXMuc3RhdGU9InN1c3RhaW4iLHRoaXMuc3RhcnRUaW1lPWgsaSk6bH1jYXNlInN1c3RhaW4iOnJldHVybiB0PD0wJiYodGhpcy5zdGF0ZT0icmVsZWFzZSIsdGhpcy5zdGFydFRpbWU9aCx0aGlzLnN0YXJ0VmFsPWkpLGk7Y2FzZSJyZWxlYXNlIjp7bGV0IHI9aC10aGlzLnN0YXJ0VGltZTtpZihyPm4pcmV0dXJuIHRoaXMuc3RhdGU9Im9mZiIsMDtsZXQgbD13KHIvbix0aGlzLnN0YXJ0VmFsLDApO3JldHVybiB0PjAmJih0aGlzLnN0YXRlPSJhdHRhY2siLHRoaXMuc3RhcnRUaW1lPWgsdGhpcy5zdGFydFZhbD1sKSxsfX10aHJvdyJpbnZhbGlkIGVudmVsb3BlIHN0YXRlIn07ZnVuY3Rpb24gdigpe3RoaXMuczA9MCx0aGlzLnMxPTB9di5wcm90b3R5cGUuYXBwbHk9ZnVuY3Rpb24oaCx0LHMpe2coIWlzTmFOKGgpLCJOYU4gdmFsdWUgZmVkIGluIFR3b1BvbGVGaWx0ZXIiKSx0PU1hdGgubWluKHQsMSkscz1NYXRoLm1heChzLDApO3ZhciBlPU1hdGgucG93KC41LCgxLXQpLy4xMjUpLGk9TWF0aC5wb3coLjUsKHMrLjEyNSkvLjEyNSksbj0xLWkqZSxyPXRoaXMuczAsbD10aGlzLnMxO3JldHVybiByPW4qci1lKmwrZSpoLGw9bipsK2UqcixoPWwsdGhpcy5zMD1yLHRoaXMuczE9bCxofTtsZXQgQT1jbGFzcyBDe2NvbnN0cnVjdG9yKHQscyl7dGhpcy5zYW1wbGVSYXRlPXQscz90aGlzLmJ1ZmZlcj1zLnNsaWNlKDApOih0aGlzLmJ1ZmZlcj1uZXcgRmxvYXQzMkFycmF5KDEwKnQpLHRoaXMuYnVmZmVyLmZpbGwoMCkpLHRoaXMud3JpdGVJZHg9MCx0aGlzLnJlYWRJZHg9MH1yZXNldCgpe3RoaXMuYnVmZmVyLmZpbGwoMCksdGhpcy53cml0ZUlkeD0wLHRoaXMucmVhZElkeD0wfWNsb25lKCl7Y29uc3QgdD1uZXcgQyh0aGlzLnNhbXBsZVJhdGUsdGhpcy5idWZmZXIpO3JldHVybiB0LndyaXRlSWR4PXRoaXMud3JpdGVJZHgsdC5yZWFkSWR4PXRoaXMucmVhZElkeCx0fXdyaXRlKHQscyl7dGhpcy53cml0ZUlkeD0odGhpcy53cml0ZUlkeCsxKSV0aGlzLmJ1ZmZlci5sZW5ndGgsdGhpcy5idWZmZXJbdGhpcy53cml0ZUlkeF09dDtsZXQgZT1NYXRoLm1pbihNYXRoLmZsb29yKHRoaXMuc2FtcGxlUmF0ZSpzKSx0aGlzLmJ1ZmZlci5sZW5ndGgtMSk7dGhpcy5yZWFkSWR4PXRoaXMud3JpdGVJZHgtZSx0aGlzLnJlYWRJZHg8MCYmKHRoaXMucmVhZElkeCs9dGhpcy5idWZmZXIubGVuZ3RoKX1yZWFkKCl7cmV0dXJuIHRoaXMuYnVmZmVyW3RoaXMucmVhZElkeF19fTtjb25zdCB5PTEvNDhlMyxNPTI0LE49TS80O2NsYXNzIG97Y29uc3RydWN0b3IodCxzLGUsaSl7dGhpcy5ub2RlSWQ9dCx0aGlzLnN0YXRlPXMsdGhpcy5zYW1wbGVSYXRlPWUsdGhpcy5zYW1wbGVUaW1lPTEvZSx0aGlzLnNlbmQ9aX19Y2xhc3MgcSBleHRlbmRzIG97Y29uc3RydWN0b3IodCxzLGUsaSl7c3VwZXIodCxzLGUsaSksdGhpcy5lbnY9bmV3IFR9dXBkYXRlKHQscyxlLGksbixyKXtyZXR1cm4gdGhpcy5lbnYuZXZhbCh0LHMsZSxpLG4scil9fWNsYXNzIEYgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMucGhhc2U9MH11cGRhdGUodCl7bGV0IHM9TSp0LzYwLGU9LjU7cmV0dXJuIHRoaXMucGhhc2UrPXRoaXMuc2FtcGxlVGltZSpzLHRoaXMucGhhc2UlMTxlPzE6LTF9fWNsYXNzIEQgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMuaW5TZ249ITAsdGhpcy5vdXRTZ249ITAsdGhpcy5jbG9ja0NudD0wfXVwZGF0ZSh0LHMpe2xldCBlPXQ+MDtyZXR1cm4gdGhpcy5pblNnbiE9ZSYmKHRoaXMuY2xvY2tDbnQrKyx0aGlzLmNsb2NrQ250Pj1zJiYodGhpcy5jbG9ja0NudD0wLHRoaXMub3V0U2duPSF0aGlzLm91dFNnbikpLHRoaXMuaW5TZ249ZSx0aGlzLm91dFNnbj8xOi0xfX1jbGFzcyBMIGV4dGVuZHMgb3tjb25zdHJ1Y3Rvcih0LHMsZSxpKXtzdXBlcih0LHMsZSxpKSx0aGlzLmluU2duPSExfXVwZGF0ZSh0LHMpe2xldCBlPXM+MDtyZXR1cm4gZSYmdGhpcy5pblNnbiE9ZSYmdGhpcy5zZW5kKHt0eXBlOiJDTE9DS19QVUxTRSIsbm9kZUlkOnRoaXMubm9kZUlkLHRpbWU6dH0pLHRoaXMuaW5TZ249ZSwwfX1jb25zdCBPPW5ldyBNYXA7Y2xhc3MgViBleHRlbmRzIG97Y29uc3RydWN0b3IodCxzLGUsaSl7c3VwZXIodCxzLGUsaSk7Y29uc3Qgbj1zLmlucHV0c1syXTtuJiZPLmhhcyhuKT90aGlzLmRlbGF5PU8uZ2V0KG4pLmNsb25lKCk6dGhpcy5kZWxheT1uZXcgQShlKSxuJiZPLnNldChuLHRoaXMuZGVsYXkpfXVwZGF0ZSh0LHMpe3JldHVybiB0aGlzLmRlbGF5LndyaXRlKHQscyksdGhpcy5kZWxheS5yZWFkKCl9fWNsYXNzIEcgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpfXVwZGF0ZSh0LHMpe3JldHVybiBrKHQscyl9fWNsYXNzIFIgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMudmFsdWU9MCx0aGlzLnRyaWdTZ249ITF9d3JpdGUodCxzKXshdGhpcy50cmlnU2duJiZzPjAmJih0aGlzLnZhbHVlPXQpLHRoaXMudHJpZ1Nnbj1zPjB9cmVhZCgpe3JldHVybiB0aGlzLnZhbHVlfXVwZGF0ZSh0LHMpe3JldHVybiB0aGlzLndyaXRlKHQscyksdGhpcy5yZWFkKCl9fWNsYXNzIEJ7Y29uc3RydWN0b3IoKXt0aGlzLnZhbHVlPTB9dXBkYXRlKHQpe3JldHVybiB0aGlzLnZhbHVlPXQsdGhpcy52YWx1ZX19Y29uc3QgJD0zNDA7bGV0IEk9MDtjbGFzcyBIe2NvbnN0cnVjdG9yKCl7dGhpcy5jaD1JLHRoaXMuc3RhcnRfc2VlZD0kKih0aGlzLmNoKzEpPj4+MCx0aGlzLnN0YXRlPXRoaXMuc3RhcnRfc2VlZCx0aGlzLnZhbHVlPTAsdGhpcy5hPTE2NjQ1MjUsdGhpcy5jPTEwMTM5MDQyMjMsdGhpcy5tYXNrPTE2Nzc3MjE1LHRoaXMuc2NhbGU9MS8oMTw8MjQpLEkrK311cGRhdGUodCxzKXtpZighdClyZXR1cm4gdGhpcy52YWx1ZTtzJiYodGhpcy5zdGF0ZT10aGlzLnN0YXJ0X3NlZWQpLHRoaXMuc3RhdGU9dGhpcy5zdGF0ZSp0aGlzLmErdGhpcy5jPj4+MDtjb25zdCBlPSh0aGlzLnN0YXRlJnRoaXMubWFzaykqdGhpcy5zY2FsZTtyZXR1cm4gdGhpcy52YWx1ZT1lKjItMSx0aGlzLnZhbHVlfX1jbGFzcyBqe2NvbnN0cnVjdG9yKCl7dGhpcy52YWx1ZT1NYXRoLnJhbmRvbSgpKjItMX11cGRhdGUodCl7cmV0dXJuIHQ/KHRoaXMudmFsdWU9TWF0aC5yYW5kb20oKSoyLTEsdGhpcy52YWx1ZSk6dGhpcy52YWx1ZX19Y2xhc3MgS3t1cGRhdGUodCl7cmV0dXJuIE1hdGgucmFuZG9tKCk8dCp5P01hdGgucmFuZG9tKCk6MH19Y2xhc3MgV3tjb25zdHJ1Y3Rvcigpe3RoaXMub3V0PTB9dXBkYXRlKCl7bGV0IHQ9TWF0aC5yYW5kb20oKSoyLTE7cmV0dXJuIHRoaXMub3V0PSh0aGlzLm91dCsuMDIqdCkvMS4wMix0aGlzLm91dH19Y2xhc3MgWHtjb25zdHJ1Y3Rvcigpe3RoaXMuYjA9MCx0aGlzLmIxPTAsdGhpcy5iMj0wLHRoaXMuYjM9MCx0aGlzLmI0PTAsdGhpcy5iNT0wLHRoaXMuYjY9MH11cGRhdGUoKXtjb25zdCB0PU1hdGgucmFuZG9tKCkqMi0xO3RoaXMuYjA9Ljk5ODg2KnRoaXMuYjArdCouMDU1NTE3OSx0aGlzLmIxPS45OTMzMip0aGlzLmIxK3QqLjA3NTA3NTksdGhpcy5iMj0uOTY5KnRoaXMuYjIrdCouMTUzODUyLHRoaXMuYjM9Ljg2NjUqdGhpcy5iMyt0Ki4zMTA0ODU2LHRoaXMuYjQ9LjU1KnRoaXMuYjQrdCouNTMyOTUyMix0aGlzLmI1PS0uNzYxNip0aGlzLmI1LXQqLjAxNjg5ODtjb25zdCBzPXRoaXMuYjArdGhpcy5iMSt0aGlzLmIyK3RoaXMuYjMrdGhpcy5iNCt0aGlzLmI1K3RoaXMuYjYrdCouNTM2MjtyZXR1cm4gdGhpcy5iNj10Ki4xMTU5MjYscyouMTF9fWNsYXNzIFkgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMucGhhc2U9MX11cGRhdGUodCl7dGhpcy5waGFzZSs9dGhpcy5zYW1wbGVUaW1lKnQ7bGV0IHM9dGhpcy5waGFzZT49MT8xOjA7cmV0dXJuIHRoaXMucGhhc2U9dGhpcy5waGFzZSUxLHN9fWNsYXNzIHogZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMucGhhc2U9MH11cGRhdGUodCxzKXtyZXR1cm4gdGhpcy5waGFzZSs9dGhpcy5zYW1wbGVUaW1lKnQsdGhpcy5waGFzZSUxPHM/MTotMX19Y2xhc3MgWiBleHRlbmRzIG97Y29uc3RydWN0b3IodCxzLGUsaSl7c3VwZXIodCxzLGUsaSksdGhpcy5waGFzZT0wfXVwZGF0ZSh0KXtyZXR1cm4gdGhpcy5waGFzZSs9dGhpcy5zYW1wbGVUaW1lKnQsdGhpcy5waGFzZSUxKjItMX19Y2xhc3MgSntjb25zdHJ1Y3Rvcigpe3RoaXMucGhhc2U9TWF0aC5yYW5kb20oKX11cGRhdGUodCl7Y29uc3Qgcz10L3NhbXBsZVJhdGU7bGV0IGU9RSh0aGlzLnBoYXNlLHMpLGk9Mip0aGlzLnBoYXNlLTEtZTtyZXR1cm4gdGhpcy5waGFzZSs9cyx0aGlzLnBoYXNlPjEmJih0aGlzLnBoYXNlLT0xKSxpfX1jbGFzcyBRIGV4dGVuZHMgb3tjb25zdHJ1Y3Rvcih0LHMsZSxpKXtzdXBlcih0LHMsZSxpKSx0aGlzLnBoYXNlPTAsdGhpcy5zeW5jU2duPSExfXVwZGF0ZSh0LHMsZSl7IXRoaXMuc3luY1NnbiYmcz4wJiYodGhpcy5waGFzZT0wKSx0aGlzLnN5bmNTZ249cz4wO2xldCBpPSh0aGlzLnBoYXNlK2UpJTE7cmV0dXJuIHRoaXMucGhhc2UrPXRoaXMuc2FtcGxlVGltZSp0LE1hdGguc2luKGkqMipNYXRoLlBJKX19Y2xhc3MgdHR7ZEJUb0xpbmVhcih0KXtyZXR1cm4gTWF0aC5wb3coMTAsdC8yMCl9bGluZWFyVG9EQih0KXtyZXR1cm4gMjAqTWF0aC5sb2cxMCh0KX11cGRhdGUodCxzLGUpe2xldCBpPXRoaXMubGluZWFyVG9EQihNYXRoLmFicyh0KSksbj0wO3JldHVybiBpPnMmJihuPShpLXMpKigxLTEvZSkpLHRoaXMuZEJUb0xpbmVhcigtbil9fWNsYXNzIHN0IGV4dGVuZHMgb3tjb25zdHJ1Y3Rvcih0LHMsZSxpKXtzdXBlcih0LHMsZSxpKSx0aGlzLnBoYXNlPTB9dXBkYXRlKHQpe3RoaXMucGhhc2UrPXRoaXMuc2FtcGxlVGltZSp0O2xldCBzPXRoaXMucGhhc2UlMTtyZXR1cm4oczwuNT8yKnM6MS0yKihzLS41KSkqMi0xfX1jbGFzcyBldCBleHRlbmRzIG97Y29uc3RydWN0b3IodCxzLGUsaSl7c3VwZXIodCxzLGUsaSk7Y29uc3Qgbj1lLzMwO2coXyhuKSksdGhpcy5idWZmZXI9bmV3IEZsb2F0MzJBcnJheShuKSx0aGlzLndyaXRlUG9zPTB9dXBkYXRlKHQscyxlLGkpe3JldHVybiB0aGlzLmJ1ZmZlclt0aGlzLndyaXRlUG9zXT10LHRoaXMud3JpdGVQb3MrKyx0aGlzLndyaXRlUG9zJXRoaXMuYnVmZmVyLmxlbmd0aD09MCYmKHRoaXMud3JpdGVQb3M9MCx0aGlzLnNlbmQoe3R5cGU6IlNFTkRfU0FNUExFUyIsaWQ6cyxzYW1wbGVzOnRoaXMuYnVmZmVyLGNoYW5uZWxzOmUsY2hhbm5lbDppfSkpLHR9fWNsYXNzIGl0e2NvbnN0cnVjdG9yKCl7dGhpcy5sYWdVbml0PTQ0MTAsdGhpcy5zPTB9dXBkYXRlKHQscyl7cmV0dXJuIHM9cyp0aGlzLmxhZ1VuaXQsczwxJiYocz0xKSx0aGlzLnMrPTEvcyoodC10aGlzLnMpLHRoaXMuc319Y2xhc3MgaHR7Y29uc3RydWN0b3IoKXt0aGlzLmxhc3Q9MH11cGRhdGUodCxzLGUpe2NvbnN0IGk9cyp5LG49ZSp5O2xldCByPXQtdGhpcy5sYXN0O3JldHVybiByPmk/cj1pOnI8LW4mJihyPS1uKSx0aGlzLmxhc3QrPXIsdGhpcy5sYXN0fX1jbGFzcyBhdCBleHRlbmRzIG97Y29uc3RydWN0b3IodCxzLGUsaSl7c3VwZXIodCxzLGUsaSksdGhpcy5zPTB9dXBkYXRlKHQscyl7cmV0dXJuIHM9cyoxZTMsczwxJiYocz0xKSx0aGlzLnMrPTEvcyoodC10aGlzLnMpLHRoaXMuc319Y2xhc3MgbnQgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMuZmlsdGVyPW5ldyB2fXVwZGF0ZSh0LHMsZSl7cmV0dXJuIHRoaXMuZmlsdGVyLmFwcGx5KHQscyxlKSx0aGlzLmZpbHRlci5zMX19Y2xhc3MgcnQgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMuZmlsdGVyPW5ldyB2fXVwZGF0ZSh0LHMsZSl7cmV0dXJuIHRoaXMuZmlsdGVyLmFwcGx5KHQscyxlKSx0aGlzLmZpbHRlci5zMH19Y2xhc3MgdXQgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpfXVwZGF0ZSh0LHMpe3JldHVybiBzPDAmJihzPTApLHM9cysxLHQ9dCpzLDQqKE1hdGguYWJzKC4yNSp0Ky4yNS1NYXRoLnJvdW5kKC4yNSp0Ky4yNSkpLS4yNSl9fWNsYXNzIGx0IGV4dGVuZHMgb3t1cGRhdGUodCl7cmV0dXJuIHR9fWNsYXNzIG0gZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMubm90ZT0wLHRoaXMuZnJlcT0wLHRoaXMudmVsb2NpdHk9MCx0aGlzLmdhdGVTdGF0ZT0ib2ZmIix0aGlzLnR5cGU9Im1pZGlpbiIsdGhpcy5jaGFubmVsPS0xfWlzRnJlZSgpe3JldHVybiB0aGlzLmdhdGVTdGF0ZT09PSJvZmYifW5vdGVPbih0LHMpe3M+MD8odGhpcy5ub3RlPXQsdGhpcy52ZWxvY2l0eT1zLHRoaXMuZnJlcT0yKiooKHQtNjkpLzEyKSo0NDAsdGhpcy5nYXRlU3RhdGU9InByZXRyaWciKTp0aGlzLm5vdGVPZmYoKX1ub3RlT2ZmKCl7dGhpcy5ub3RlPTAsdGhpcy5nYXRlU3RhdGU9Im9mZiJ9Z2V0R2F0ZSgpe3N3aXRjaCh0aGlzLmdhdGVTdGF0ZSl7Y2FzZSJwcmV0cmlnIjpyZXR1cm4gdGhpcy5nYXRlU3RhdGU9Im9uIiwwO2Nhc2Uib24iOnJldHVybiAxO2Nhc2Uib2ZmIjpyZXR1cm4gMDtkZWZhdWx0OmcoITEpfX1nZXRGcmVxKCl7c3dpdGNoKHRoaXMuZ2F0ZVN0YXRlKXtjYXNlInByZXRyaWciOnJldHVybiB0aGlzLmdhdGVTdGF0ZT0ib24iLDA7Y2FzZSJvbiI6cmV0dXJuIHRoaXMuZnJlcTtjYXNlIm9mZiI6cmV0dXJuIHRoaXMuZnJlcTtkZWZhdWx0OmcoITEpfX1nZXRWZWxvY2l0eSgpe3N3aXRjaCh0aGlzLmdhdGVTdGF0ZSl7Y2FzZSJwcmV0cmlnIjpyZXR1cm4gdGhpcy5nYXRlU3RhdGU9Im9uIiwwO2Nhc2Uib24iOnJldHVybiB0aGlzLnZlbG9jaXR5O2Nhc2Uib2ZmIjpyZXR1cm4gdGhpcy52ZWxvY2l0eTtkZWZhdWx0OmcoITEpfX19Y2xhc3Mgb3QgZXh0ZW5kcyBte2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMudHlwZT0ibWlkaWdhdGUifXVwZGF0ZSh0KXtyZXR1cm4gdGhpcy5jaGFubmVsPXQsdGhpcy5nZXRHYXRlKCl9fWNsYXNzIGN0IGV4dGVuZHMgbXtjb25zdHJ1Y3Rvcih0LHMsZSxpKXtzdXBlcih0LHMsZSxpKSx0aGlzLnR5cGU9Im1pZGlmcmVxIn11cGRhdGUodCl7cmV0dXJuIHRoaXMuY2hhbm5lbD10LHRoaXMuZ2V0RnJlcSgpfX1jbGFzcyBkdCBleHRlbmRzIG17Y29uc3RydWN0b3IodCxzLGUsaSl7c3VwZXIodCxzLGUsaSksdGhpcy50eXBlPSJtaWRpdmVsIn11cGRhdGUodCl7cmV0dXJuIHRoaXMuY2hhbm5lbD10LHRoaXMuZ2V0VmVsb2NpdHkoKX19Y2xhc3MgZnR7Y29uc3RydWN0b3IodCxzLGUsaSl7dGhpcy51cD0hMSx0aGlzLnNlbmQ9aSx0aGlzLnZhbHVlPTAsdGhpcy50eXBlPSJjYyJ9c2V0VmFsdWUodCl7dGhpcy52YWx1ZT10fXVwZGF0ZSh0LHMsZSl7cmV0dXJuIHRoaXMuaWQ9cywhdGhpcy51cCYmdD4wPyh0aGlzLnVwPSEwLHRoaXMuc2VuZCh7dHlwZToiU0lHTkFMX1RSSUdHRVIiLGlkOnMsdGltZTplfSksdGhpcy52YWx1ZSk6KHRoaXMudXA9dD4wLHRoaXMudmFsdWUpfX1jbGFzcyBwdCBleHRlbmRzIG97Y29uc3RydWN0b3IodCxzLGUsaSl7c3VwZXIodCxzLGUsaSksdGhpcy50eXBlPSJjYyIsdGhpcy52YWx1ZT1zLmlucHV0c1sxXT8/MH1zZXRWYWx1ZSh0KXt0aGlzLnZhbHVlPXR9dXBkYXRlKHQpe3JldHVybiB0aGlzLmlkPXQsdGhpcy52YWx1ZX19Y2xhc3MgYnQgZXh0ZW5kcyBve2NvbnN0cnVjdG9yKHQscyxlLGkpe3N1cGVyKHQscyxlLGkpLHRoaXMudHlwZT0ibWlkaWNjIix0aGlzLnZhbHVlPXMuaW5wdXRzWzJdPz8tMSx0aGlzLmNoYW5uZWw9LTEsdGhpcy5jY251bWJlcj0tMX1zZXRWYWx1ZSh0KXt0aGlzLnZhbHVlPXR9dXBkYXRlKHQscyl7cmV0dXJuIHRoaXMuY2NudW1iZXI9dCx0aGlzLmNoYW5uZWw9cyx0aGlzLnZhbHVlfX1jbGFzcyBndCBleHRlbmRzIG97Y29uc3RydWN0b3IodCxzLGUsaSl7c3VwZXIodCxzLGUsaSksdGhpcy5jbG9ja1Nnbj0hMCx0aGlzLnN0ZXA9MCx0aGlzLmZpcnN0PSEwfXVwZGF0ZSh0LC4uLnMpe3JldHVybiF0aGlzLmNsb2NrU2duJiZ0PjA/KHRoaXMuc3RlcD0odGhpcy5zdGVwKzEpJXMubGVuZ3RoLHRoaXMuY2xvY2tTZ249dD4wLDApOih0aGlzLmNsb2NrU2duPXQ+MCxzW3RoaXMuc3RlcF0pfX1jbGFzcyBtdCBleHRlbmRzIG97dXBkYXRlKHQsLi4ucyl7Y29uc3QgZT10JXMubGVuZ3RoK3MubGVuZ3RoO3JldHVybiBzW01hdGguZmxvb3IoZSklcy5sZW5ndGhdfX1jbGFzcyBTdHt1cGRhdGUodCxzLGUsaSxuKXtsZXQgcj1QKHQscyxlKTtyZXR1cm4gUyhyLGksbil9fWNsYXNzIHd0e3VwZGF0ZSh0LHMsZSl7cmV0dXJuIE1hdGgubWluKE1hdGgubWF4KHQscyksZSl9fWNsYXNzIHZ0e2NvbnN0cnVjdG9yKCl7dGhpcy5oaT0hMX11cGRhdGUodCl7cmV0dXJuIXRoaXMuaGkmJnQ+MD8odGhpcy5oaT0hMCwxKToodGhpcy5oaSYmdDw9MCYmKHRoaXMuaGk9ITEpLDApfX1jbGFzcyB5dHtjb25zdHJ1Y3Rvcigpe3RoaXMueDE9MCx0aGlzLngyPTAsdGhpcy55MT0wLHRoaXMueTI9MCx0aGlzLmEwPTEsdGhpcy5hMT0wLHRoaXMuYTI9MCx0aGlzLmIwPTEsdGhpcy5iMT0wLHRoaXMuYjI9MH11cGRhdGUodD0wLHM9MCxlPTUwMCxpPTEsbj0xKXtjb25zdCByPTIqTWF0aC5QSSplL3NhbXBsZVJhdGUsbD1NYXRoLnNpbihyKTtpPU1hdGgucG93KDEwLGkvMjApO2NvbnN0IHU9bC8oMippKSxjPU1hdGguY29zKHIpO2lmKHM9PT0wKXRoaXMuYjE9MS1jLHRoaXMuYjA9dGhpcy5iMS8yLHRoaXMuYjI9dGhpcy5iMCx0aGlzLmEwPTErdSx0aGlzLmExPS0yKmMsdGhpcy5hMj0xLXU7ZWxzZSBpZihzPT09MSl0aGlzLmIwPSgxK2MpLzIsdGhpcy5iMT0tKDErYyksdGhpcy5iMj10aGlzLmIwLHRoaXMuYTA9MSt1LHRoaXMuYTE9LTIqYyx0aGlzLmEyPTEtdTtlbHNlIGlmKHM9PT0yKXRoaXMuYjA9bC8yLHRoaXMuYjE9MCx0aGlzLmIyPS10aGlzLmIwLHRoaXMuYTA9MSt1LHRoaXMuYTE9LTIqYyx0aGlzLmEyPTEtdTtlbHNlIGlmKHM9PT0zKXRoaXMuYjA9MSx0aGlzLmIxPS0yKmMsdGhpcy5iMj0xLHRoaXMuYTA9MSt1LHRoaXMuYTE9LTIqYyx0aGlzLmEyPTEtdTtlbHNlIGlmKHM9PT00KXRoaXMuYjA9MS11LHRoaXMuYjE9LTIqYyx0aGlzLmIyPTErdSx0aGlzLmEwPTErdSx0aGlzLmExPS0yKmMsdGhpcy5hMj0xLXU7ZWxzZSBpZihzPT09NSl7Y29uc3QgYT1NYXRoLnBvdygxMCxuLzQwKTt0aGlzLmIwPTErdSphLHRoaXMuYjE9LTIqYyx0aGlzLmIyPTEtdSphLHRoaXMuYTA9MSt1L2EsdGhpcy5hMT0tMipjLHRoaXMuYTI9MS11L2F9ZWxzZSBpZihzPT09Nil7Y29uc3QgYT1NYXRoLnBvdygxMCxuLzQwKSxkPTIqTWF0aC5zcXJ0KGEpKnUsZj0oYS0xKSpjLHA9KGErMSkqYzt0aGlzLmIwPWEqKGErMS1mK2QpLHRoaXMuYjE9MiphKihhLTEtcCksdGhpcy5iMj1hKihhKzEtZi1kKSx0aGlzLmEwPWErMStmK2QsdGhpcy5hMT0tMiooYS0xK3ApLHRoaXMuYTI9YSsxK2YtZH1lbHNlIGlmKHM9PT03KXtjb25zdCBhPU1hdGgucG93KDEwLG4vNDApLGQ9MipNYXRoLnNxcnQoYSkqdSxmPShhLTEpKmMscD0oYSsxKSpjO3RoaXMuYjA9YSooYSsxK2YrZCksdGhpcy5iMT0tMiphKihhLTErcCksdGhpcy5iMj1hKihhKzErZi1kKSx0aGlzLmEwPWErMS1mK2QsdGhpcy5hMT0yKihhLTEtcCksdGhpcy5hMj1hKzEtZi1kfXRoaXMuYjAvPXRoaXMuYTAsdGhpcy5iMS89dGhpcy5hMCx0aGlzLmIyLz10aGlzLmEwLHRoaXMuYTEvPXRoaXMuYTAsdGhpcy5hMi89dGhpcy5hMCx0aGlzLmEwPTE7Y29uc3QgYj10aGlzLmIwKnQrdGhpcy5iMSp0aGlzLngxK3RoaXMuYjIqdGhpcy54Mi10aGlzLmExKnRoaXMueTEtdGhpcy5hMip0aGlzLnkyO3JldHVybiB0aGlzLngyPXRoaXMueDEsdGhpcy54MT10LHRoaXMueTI9dGhpcy55MSx0aGlzLnkxPWIsYn19Y29uc3QgTXQ9T2JqZWN0LmZyZWV6ZShPYmplY3QuZGVmaW5lUHJvcGVydHkoe19fcHJvdG9fXzpudWxsLEFEU1JOb2RlOnEsQXVkaW9JbjpsdCxBdWRpb05vZGU6byxCUEY6cnQsQmlxdWFkRmlsdGVyOnl0LEJyb3duTm9pc2VPc2M6VyxDQzpwdCxDTE9DS19QUFE6TSxDTE9DS19QUFM6TixDbGlwOnd0LENsb2NrOkYsQ2xvY2tEaXY6RCxDbG9ja091dDpMLERlbGF5OlYsRGlzdG9ydDpHLER1c3RPc2M6SyxGaWx0ZXI6bnQsRm9sZDp1dCxIb2xkOlIsSW1wdWxzZU9zYzpZLExhZzppdCxMY2dOb2lzZTpILE1pZGlDQzpidCxNaWRpRnJlcTpjdCxNaWRpR2F0ZTpvdCxNaWRpSW46bSxNaWRpVmVsOmR0LE5vaXNlT3NjOmosT3V0cHV0OkIsUGljazptdCxQaW5rTm9pc2U6WCxQdWxzZU9zYzp6LFJlbWFwOlN0LFNhd09zYzpKLFNjb3BlOmV0LFNlcXVlbmNlOmd0LFNpZGVjaGFpbkNvbXByZXNzb3I6dHQsU2lnbmFsOmZ0LFNpbmVPc2M6USxTbGV3Omh0LFNsaWRlOmF0LFRyaU9zYzpzdCxUcmlnOnZ0LFphd09zYzpafSxTeW1ib2wudG9TdHJpbmdUYWcse3ZhbHVlOiJNb2R1bGUifSkpLHg9bmV3IE1hcChPYmplY3QuZW50cmllcyhNdCkpO2NsYXNzIE90e2NvbnN0cnVjdG9yKHQscyl7Zyh0PT00OGUzKSx0aGlzLnNhbXBsZVJhdGU9dCx0aGlzLnBsYXlQb3M9MCx0aGlzLnNlbmQ9cyx0aGlzLnVuaXRzPVtdLHRoaXMudW5pdElEPTAsdGhpcy5mYWRlVGltZT0uMDEsdGhpcy5tYXhVbml0cz0xLHRoaXMucT1bXX1mYWRlT3V0VW5pdCh0KXt0LmZhZGVPdXQodGhpcy5wbGF5UG9zLHRoaXMuZmFkZVRpbWUpLHRoaXMuZnJlZVVuaXQodC5pZCx0aGlzLmZhZGVUaW1lKX1mYWRlT3V0VW5pdEJ5SWQodCl7Y29uc3Qgcz10aGlzLnVuaXRzLmZpbmQoZT0+ZS5pZD09PXQpO3MmJnRoaXMuZmFkZU91dFVuaXQocyl9ZmFkZU91dEFsbFVuaXRzKCl7dGhpcy51bml0cy5mb3JFYWNoKHQ9PnRoaXMuZmFkZU91dFVuaXQodCkpfWZhZGVPdXRPbGRVbml0cygpe2NvbnN0IHQ9dGhpcy51bml0cy5maWx0ZXIoZT0+ZS5hY3RpdmUpLHM9dC5sZW5ndGgtdGhpcy5tYXhVbml0cztzPD0wfHx0LnNsaWNlKDAscykuZm9yRWFjaChlPT50aGlzLmZhZGVPdXRVbml0KGUpKX1zdG9wKCl7dGhpcy5mYWRlT3V0QWxsVW5pdHMoKSx0aGlzLnNlbmQoe3R5cGU6IlNUT1AiLGZhZGVUaW1lOnRoaXMuZmFkZVRpbWV9KX1zcGF3blVuaXQodCxzKXtjb25zdCBlPW5ldyB4dCh0aGlzLnVuaXRJRCsrLHQsdGhpcy5zYW1wbGVSYXRlLHRoaXMuc2VuZCk7dGhpcy51bml0cy5wdXNoKGUpLGUuZmFkZUluKHRoaXMucGxheVBvcyx0aGlzLmZhZGVUaW1lKSx0aGlzLmZhZGVPdXRPbGRVbml0cygpLGNvbnNvbGUubG9nKGBzcGF3biB1bml0ICR7ZS5pZH0sIHVuaXRzIGFsaXZlOiAke3RoaXMudW5pdHMubGVuZ3RofWApLHMmJnRoaXMuc2NoZWR1bGVNZXNzYWdlKHttc2c6e3R5cGU6IkZBREVfT1VUX1VOSVQiLGlkOmUuaWR9LHRpbWU6c30pfWZyZWVVbml0KHQscyl7aWYocyl7dGhpcy5zY2hlZHVsZU1lc3NhZ2Uoe21zZzp7dHlwZToiRlJFRV9VTklUIixpZDp0fSx0aW1lOnN9KTtyZXR1cm59Y29uc3QgZT10aGlzLnVuaXRzLmxlbmd0aDt0aGlzLnVuaXRzPXRoaXMudW5pdHMuZmlsdGVyKGk9PmkuaWQhPT10KSxlPnRoaXMudW5pdHMubGVuZ3RoJiZjb25zb2xlLmxvZyhgZnJlZSB1bml0ICR7dH0sIHVuaXRzIGFsaXZlOiAke3RoaXMudW5pdHMubGVuZ3RofWApfXBhcnNlTXNnKHQpe3N3aXRjaCh0LnR5cGUpe2Nhc2UiU1BBV05fVU5JVCI6dGhpcy5zcGF3blVuaXQodC51bml0LHQuZHVyYXRpb24pO2JyZWFrO2Nhc2UiRlJFRV9VTklUIjp0aGlzLmZyZWVVbml0KHQuaWQpO2JyZWFrO2Nhc2UiRkFERV9PVVRfVU5JVCI6dGhpcy5mYWRlT3V0VW5pdEJ5SWQodC5pZCk7YnJlYWs7Y2FzZSJOT1RFX09OIjp0aGlzLm5vdGVPbih0KTticmVhaztjYXNlIkNDIjp0aGlzLm1pZGlDQyh0KTticmVhaztjYXNlIlNFVF9DT05UUk9MIjp0aGlzLnNldENvbnRyb2wodCk7YnJlYWs7Y2FzZSJGQURFX1RJTUUiOnRoaXMuZmFkZVRpbWU9TnVtYmVyKHQuZmFkZVRpbWUpO2JyZWFrO2Nhc2UiTUFYX1VOSVRTIjp0aGlzLm1heFVuaXRzPU51bWJlcih0Lm1heFVuaXRzKTticmVhaztjYXNlIlNUT1AiOnRoaXMuc3RvcCgpO2JyZWFrO2Nhc2UiU0VUX1VHRU4iOnRoaXMuYWRkVWdlbih0LmNsYXNzTmFtZSx0LnVnZW4pO2JyZWFrO2Nhc2UiU0NIRURVTEVfTVNHIjp0aGlzLnNjaGVkdWxlTWVzc2FnZSh0KTticmVhaztjYXNlIkJBVENIX01TRyI6dC5tZXNzYWdlcy5mb3JFYWNoKHM9PnRoaXMucGFyc2VNc2cocykpO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IFR5cGVFcnJvcihgdW5rbm93biBtZXNzYWdlIHR5cGUgJHt0LnR5cGV9YCl9fW5vdGVPbih0KXt0aGlzLnVuaXRzLmZvckVhY2gocz0+cy5ub3RlT24odCkpfW1pZGlDQyh0KXt0aGlzLnVuaXRzLmZvckVhY2gocz0+cy5taWRpQ0ModCkpfXNldENvbnRyb2wodCl7dGhpcy51bml0cy5mb3JFYWNoKHM9PnMuc2V0Q29udHJvbCh0KSl9c2NoZWR1bGVNZXNzYWdlKHQpe2lmKHQudGltZT10aGlzLnBsYXlQb3MrdC50aW1lLCF0aGlzLnEubGVuZ3RoKXt0aGlzLnEucHVzaCh0KTtyZXR1cm59bGV0IHM9MDtmb3IoO3M8dGhpcy5xLmxlbmd0aCYmdGhpcy5xW3NdLnRpbWU8dC50aW1lOylzKys7dGhpcy5xLnNwbGljZShzLDAsdCl9Z2VuU2FtcGxlKHQpe2Zvcig7dGhpcy5xLmxlbmd0aD4wJiZ0aGlzLnFbMF0udGltZTw9dGhpcy5wbGF5UG9zOyl0aGlzLnBhcnNlTXNnKHRoaXMucVswXS5tc2cpLHRoaXMucS5zaGlmdCgpO2lmKCF0aGlzLnVuaXRzLmxlbmd0aClyZXR1cm5bMCwwXTtjb25zdCBzPVswLDBdO2ZvcihsZXQgZT0wO2U8dGhpcy51bml0cy5sZW5ndGg7ZSsrKXtjb25zdCBpPXRoaXMudW5pdHNbZV0sbj1pLmdldExldmVsKHRoaXMucGxheVBvcyk7aS5nZW5TYW1wbGUodGhpcy5wbGF5UG9zLGkubm9kZXMsdCxpLnJlZ2lzdGVycyxpLm91dHB1dHMsaS5zb3VyY2VzKSxzWzBdKz1pLm91dHB1dHNbMF0qbixzWzFdKz1pLm91dHB1dHNbMV0qbn1yZXR1cm4gdGhpcy5wbGF5UG9zKz0xLzQ4ZTMsc31hZGRVZ2VuKHQscyl7Y29uc3QgZT1uZXcgRnVuY3Rpb24oYCR7c307cmV0dXJuICR7dH1gKSgpO3guc2V0KHQsZSl9fWNsYXNzIHh0e2NvbnN0cnVjdG9yKHQscyxlLGkpe3RoaXMuaWQ9dCx0aGlzLnNhbXBsZVJhdGU9ZSx0aGlzLnNlbmQ9aSx0aGlzLm5vZGVzPVtdLHRoaXMuYWN0aXZlPSEwO2ZvcihsZXQgciBpbiBzLnVnZW5zKXtjb25zdCBsPXMudWdlbnNbcl07aWYoeC5oYXMobC50eXBlKSl7Y29uc3QgdT14LmdldChsLnR5cGUpLGM9TnVtYmVyKHIpO3RoaXMubm9kZXNbY109bmV3IHUoYyxsLHRoaXMuc2FtcGxlUmF0ZSx0aGlzLnNlbmQpfWVsc2UgY29uc29sZS53YXJuKGB1bmtub3duIHVnZW4gIiR7bC50eXBlfSJgKX10aGlzLnJlZ2lzdGVycz1uZXcgQXJyYXkocy5yZWdpc3RlcnMpLmZpbGwoMCk7bGV0IG49MTY7dGhpcy5vdXRwdXRzPW5ldyBBcnJheShuKS5maWxsKDApLHRoaXMuc291cmNlcz1uZXcgQXJyYXkobikuZmlsbCgwKSxzLnNyYz1gby5maWxsKDApOyAvLyByZXNldCBvdXRwdXRzCmArcy5zcmMsdGhpcy5nZW5TYW1wbGU9bmV3IEZ1bmN0aW9uKCJ0aW1lIiwibm9kZXMiLCJpbnB1dCIsInIiLCJvIiwicyIscy5zcmMpfW5vdGVPbih0KXt2YXIgdSxjLGI7Y29uc3R7Y2hhbm5lbDpzLG5vdGU6ZSx2ZWxvY2l0eTppfT10LG49dGhpcy5ub2Rlcy5maWx0ZXIoYT0+YS50eXBlPT09Im1pZGlmcmVxIiYmKGEuY2hhbm5lbD09PS0xfHxhLmNoYW5uZWw9PT1zKSkscj10aGlzLm5vZGVzLmZpbHRlcihhPT5hLnR5cGU9PT0ibWlkaWdhdGUiJiYoYS5jaGFubmVsPT09LTF8fGEuY2hhbm5lbD09PXMpKSxsPXRoaXMubm9kZXMuZmlsdGVyKGE9PmEudHlwZT09PSJtaWRpdmVsIiYmKGEuY2hhbm5lbD09PS0xfHxhLmNoYW5uZWw9PT1zKSk7aWYoaT4wKXtsZXQgYT1uLmZpbmQocD0+cC5pc0ZyZWUoKSl8fG5bMF0sZD1yLmZpbmQocD0+cC5pc0ZyZWUoKSl8fHJbMF0sZj1sLmZpbmQocD0+cC5pc0ZyZWUoKSl8fGxbMF07YT09bnVsbHx8YS5ub3RlT24oZSxpKSxkPT1udWxsfHxkLm5vdGVPbihlLGkpLGY9PW51bGx8fGYubm90ZU9uKGUsaSl9ZWxzZSh1PW4uZmluZChhPT5hLm5vdGU9PT1lKSk9PW51bGx8fHUubm90ZU9mZigpLChjPXIuZmluZChhPT5hLm5vdGU9PT1lKSk9PW51bGx8fGMubm90ZU9mZigpLChiPWwuZmluZChhPT5hLm5vdGU9PT1lKSk9PW51bGx8fGIubm90ZU9mZigpfW1pZGlDQyh0KXtjb25zdHtjaGFubmVsOnMsY2M6ZSx2YWx1ZTppfT10O3RoaXMubm9kZXMuZm9yRWFjaChuPT57bi50eXBlPT09Im1pZGljYyImJihuLmNoYW5uZWw9PT0tMXx8bi5jaGFubmVsPT09cykmJm4uY2NudW1iZXI9PT1lJiZuLnNldFZhbHVlKGkpfSl9c2V0Q29udHJvbCh0KXtjb25zdHt2YWx1ZTpzLGlkOmV9PXQsaT10aGlzLm5vZGVzLmZpbmQobj0+bi50eXBlPT09ImNjIiYmbi5pZD09PWUpO2kmJmkuc2V0VmFsdWUocyl9Z2V0TGV2ZWwodCl7cmV0dXJuIHRoaXMuZmFkZVN0YXJ0PT09dm9pZCAwPzA6dGhpcy5hY3RpdmU/UygodC10aGlzLmZhZGVTdGFydCkvdGhpcy5mYWRlVGltZSwwLC4zKTpTKCh0LXRoaXMuZmFkZVN0YXJ0KS90aGlzLmZhZGVUaW1lLHRoaXMuZmFkZUZyb20sMCl9ZmFkZUluKHQscyl7dGhpcy5mYWRlU3RhcnQ9dCx0aGlzLmZhZGVUaW1lPXN9ZmFkZU91dCh0LHMpe3RoaXMuZmFkZVRpbWU9cyx0aGlzLmZhZGVGcm9tPXRoaXMuZ2V0TGV2ZWwodCksdGhpcy5hY3RpdmU9ITEsdGhpcy5mYWRlU3RhcnQ9dH1pc0RvbmUodCl7cmV0dXJuIXRoaXMuYWN0aXZlJiZ0aGlzLmdldExldmVsKHQpPT09MH19Y2xhc3MgVHQgZXh0ZW5kcyBBdWRpb1dvcmtsZXRQcm9jZXNzb3J7Y29uc3RydWN0b3IoKXtzdXBlcigpLHRoaXMucG9ydC5vbm1lc3NhZ2U9dGhpcy5vbm1lc3NhZ2UuYmluZCh0aGlzKSx0aGlzLmF1ZGlvR3JhcGg9bmV3IE90KDQ4ZTMsdGhpcy5wb3J0LnBvc3RNZXNzYWdlLmJpbmQodGhpcy5wb3J0KSl9b25tZXNzYWdlKHQpe2xldCBzPXQuZGF0YTt0aGlzLmF1ZGlvR3JhcGgucGFyc2VNc2cocyl9cHJvY2Vzcyh0LHMsZSl7Y29uc3QgaT1zWzBdLG49dFswXVswXSxyPWlbMF0sbD1pWzFdO2ZvcihsZXQgdT0wO3U8ci5sZW5ndGg7dSsrKXtsZXRbYyxiXT10aGlzLmF1ZGlvR3JhcGguZ2VuU2FtcGxlKG4/blt1XTowKTtyW3VdPWMsbFt1XT1ifXJldHVybiEwfX1yZWdpc3RlclByb2Nlc3Nvcigic2FtcGxlLWdlbmVyYXRvciIsVHQpfSkoKTsK", Ge = "data:text/javascript;base64,KGZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2NsYXNzIG4gZXh0ZW5kcyBBdWRpb1dvcmtsZXRQcm9jZXNzb3J7c3RhdGljIGdldCBwYXJhbWV0ZXJEZXNjcmlwdG9ycygpe3JldHVyblt7bmFtZToiaXNSZWNvcmRpbmciLGRlZmF1bHRWYWx1ZTowfV19Y29uc3RydWN0b3IoKXtzdXBlcigpLHRoaXMuX2J1ZmZlclNpemU9MjA0OCx0aGlzLl9idWZmZXI9bmV3IEZsb2F0MzJBcnJheSh0aGlzLl9idWZmZXJTaXplKSx0aGlzLl9pbml0QnVmZmVyKCl9X2luaXRCdWZmZXIoKXt0aGlzLl9ieXRlc1dyaXR0ZW49MH1faXNCdWZmZXJFbXB0eSgpe3JldHVybiB0aGlzLl9ieXRlc1dyaXR0ZW49PT0wfV9pc0J1ZmZlckZ1bGwoKXtyZXR1cm4gdGhpcy5fYnl0ZXNXcml0dGVuPT09dGhpcy5fYnVmZmVyU2l6ZX1fYXBwZW5kVG9CdWZmZXIoZSl7dGhpcy5faXNCdWZmZXJGdWxsKCkmJnRoaXMuX2ZsdXNoKCksdGhpcy5fYnVmZmVyW3RoaXMuX2J5dGVzV3JpdHRlbl09ZSx0aGlzLl9ieXRlc1dyaXR0ZW4rPTF9X2ZsdXNoKCl7bGV0IGU9dGhpcy5fYnVmZmVyO3RoaXMuX2J5dGVzV3JpdHRlbjx0aGlzLl9idWZmZXJTaXplJiYoZT1lLnNsaWNlKDAsdGhpcy5fYnl0ZXNXcml0dGVuKSksdGhpcy5wb3J0LnBvc3RNZXNzYWdlKHtldmVudFR5cGU6ImRhdGEiLGF1ZGlvQnVmZmVyOmV9KSx0aGlzLl9pbml0QnVmZmVyKCl9X3JlY29yZGluZ1N0b3BwZWQoKXt0aGlzLnBvcnQucG9zdE1lc3NhZ2Uoe2V2ZW50VHlwZToic3RvcCJ9KX1wcm9jZXNzKGUsbyxoKXtjb25zdCBpPWguaXNSZWNvcmRpbmcsZj1vWzBdLHM9ZVswXSx1PWZbMF0sXz1mWzFdO2xldCByPSExO2ZvcihsZXQgdD0wO3Q8dS5sZW5ndGg7dCsrKXQ8aS5sZW5ndGgmJihyPWlbdF09PT0xKSwhciYmIXRoaXMuX2lzQnVmZmVyRW1wdHkoKSYmKHRoaXMuX2ZsdXNoKCksdGhpcy5fcmVjb3JkaW5nU3RvcHBlZCgpKSxyJiYodGhpcy5fYXBwZW5kVG9CdWZmZXIoc1swXVt0XSksdGhpcy5fYXBwZW5kVG9CdWZmZXIoc1sxXVt0XSkpLHVbdF09c1swXVt0XSxfW3RdPXNbMV1bdF07cmV0dXJuITB9fXJlZ2lzdGVyUHJvY2Vzc29yKCJyZWNvcmRlciIsbil9KSgpOwo=";
|
|
function ye(e, a, n) {
|
|
if (e.length < 1)
|
|
return;
|
|
e[0];
|
|
const t = 3, s = 32, o = e.map((f) => f.length).reduce((f, z) => f + z, 0), d = s / 8, G = n * d, p = 44, h = new ArrayBuffer(p + o * d), m = new DataView(h);
|
|
V(m, 0, "RIFF"), m.setUint32(4, 36 + o * d, !0), V(m, 8, "WAVE"), V(m, 12, "fmt "), m.setUint32(16, 16, !0), m.setUint16(20, t, !0), m.setUint16(22, n, !0), m.setUint32(24, a, !0), m.setUint32(28, a * G, !0), m.setUint16(32, G, !0), m.setUint16(34, s, !0), V(m, 36, "data"), m.setUint32(40, o * d, !0);
|
|
let R = 44;
|
|
for (const f of e)
|
|
Xe(m, R, f), R += f.length * d;
|
|
return h;
|
|
}
|
|
function V(e, a, n) {
|
|
for (let t = 0; t < n.length; t++)
|
|
e.setUint8(a + t, n.charCodeAt(t));
|
|
}
|
|
function Xe(e, a, n) {
|
|
for (var t = 0; t < n.length; t++, a += 4)
|
|
e.setFloat32(a, n[t], !0);
|
|
}
|
|
const k = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
__proto__: null,
|
|
Node: c,
|
|
compile: T,
|
|
evaluate: j,
|
|
exit: J,
|
|
exportModule: ce,
|
|
getInletName: oe,
|
|
getNode: F,
|
|
module: y,
|
|
n: X,
|
|
node: x,
|
|
nodeRegistry: g,
|
|
outputType: Y,
|
|
polyType: Z,
|
|
register: u,
|
|
registerNode: l
|
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
let fe = (e) => `Math.sin(${e})`, Ze = (e) => `Math.cos(${e})`, be = (e) => `Math.tan(${e})`, xe = (e) => `Math.asin(${e})`, Re = (e) => `Math.acos(${e})`, Le = (e) => `Math.atan(${e})`, B = (e, a, n) => `${e} = ${a};${n ? ` /* ${n} */` : ""}`, w = (e, ...a) => B(
|
|
e.name,
|
|
`nodes[${e.ugenIndex}].update(${a.join(",")})`,
|
|
e.node.type
|
|
), Me = (e) => `(2 ** ((${e} - 69) / 12) * 440)`, ze = (e, a) => `${e} ** ${a}`, Ve = (e) => `Math.exp(${e})`, We = (e) => `Math.log(${e})`, Ye = (e, a) => `${e}%${a}`, Ne = (e) => `Math.abs(${e})`, He = (e) => `Math.round(${e})`, Se = (e) => `Math.floor(${e})`, Te = (e) => `Math.sign(${e})`, we = (e) => `Math.ceil(${e})`, ve = (e, a) => `Math.min(${e}, ${a})`, Ke = (e, a) => `Math.max(${e}, ${a})`, Ce = (e, a) => `[${e}, ${a}]`, L = (e) => `${e}[0]`, Ie = (e) => `${e}[1]`, Ue = (e, a) => `(${L(e)} < ${L(a)} ? ${e} : ${a})`, ke = (e, a) => `(${L(e)} > ${L(a)} ? ${e} : ${a})`;
|
|
const Pe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
__proto__: null,
|
|
abs: Ne,
|
|
ceil: we,
|
|
def: B,
|
|
defAcos: Re,
|
|
defAsin: xe,
|
|
defAtan: Le,
|
|
defCos: Ze,
|
|
defSin: fe,
|
|
defTan: be,
|
|
defUgen: w,
|
|
exp: Ve,
|
|
floor: Se,
|
|
log: We,
|
|
max: Ke,
|
|
midinote: Me,
|
|
min: ve,
|
|
mod: Ye,
|
|
pair_a: L,
|
|
pair_a_max: ke,
|
|
pair_a_min: Ue,
|
|
pair_b: Ie,
|
|
pair_make: Ce,
|
|
pow: ze,
|
|
round: He,
|
|
sign: Te
|
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
class Fe {
|
|
constructor(a = null) {
|
|
this.ugens = /* @__PURE__ */ new Map(), this.outputNode = a;
|
|
}
|
|
async spawn(a, n) {
|
|
this.graph = a;
|
|
const { src: t, ugens: s, registers: o } = a.compile({
|
|
log: !1
|
|
});
|
|
!this.mouse && t.includes("mouse") && this.initMouse(), !this.midiInited && s.some((d) => d.type.startsWith("Midi")) && this.initMidi(), !this.audioIn && s.some((d) => d.type === "AudioIn") && await this.initAudioIn(), this.sendCustomUgens(), this.send({
|
|
type: "SPAWN_UNIT",
|
|
unit: { src: t, ugens: s, registers: o },
|
|
duration: n
|
|
// experimental
|
|
});
|
|
}
|
|
// ugen is expected to be a class
|
|
registerUgen(a) {
|
|
this.ugens.set(a.name, a);
|
|
}
|
|
// custom ugens
|
|
sendCustomUgens() {
|
|
if (!this.ugens.size)
|
|
return;
|
|
let a = [];
|
|
for (let [n, t] of this.ugens)
|
|
a.push({
|
|
type: "SET_UGEN",
|
|
className: n,
|
|
ugen: t + ""
|
|
});
|
|
this.send({
|
|
type: "BATCH_MSG",
|
|
messages: a
|
|
});
|
|
}
|
|
scheduleMessage(a, n) {
|
|
this.send({
|
|
type: "SCHEDULE_MSG",
|
|
msg: a,
|
|
time: n
|
|
});
|
|
}
|
|
setControl(a, n, t) {
|
|
const s = {
|
|
type: "SET_CONTROL",
|
|
id: a,
|
|
value: n
|
|
};
|
|
t ? this.send({ type: "SCHEDULE_MSG", time: t, msg: s }) : this.send(s);
|
|
}
|
|
// controls: { id, value, time }[]
|
|
setControls(a) {
|
|
const n = {
|
|
type: "BATCH_MSG",
|
|
messages: a.map((t) => {
|
|
const s = { type: "SET_CONTROL", id: t.id, value: t.value };
|
|
return t.time === void 0 ? s : {
|
|
type: "SCHEDULE_MSG",
|
|
time: t.time,
|
|
msg: s
|
|
};
|
|
})
|
|
};
|
|
this.send(n);
|
|
}
|
|
async initAudioIn() {
|
|
console.log("init audio input...");
|
|
const a = await navigator.mediaDevices.getUserMedia({
|
|
audio: {
|
|
echoCancellation: !1,
|
|
noiseSuppression: !1,
|
|
autoGainControl: !1
|
|
}
|
|
});
|
|
this.audioCtx.createMediaStreamSource(a).connect(this.audioWorklet);
|
|
}
|
|
initMidi() {
|
|
console.log("init midi input..."), this.midiInited = !0, new me().on("midimessage", (a, n) => {
|
|
const t = re(n);
|
|
t && this.send(t);
|
|
});
|
|
}
|
|
initMouse() {
|
|
console.log("init mouse"), this.mouse = new he(), this.mouse.on("move", (a, n) => {
|
|
this.setControl("mouseX", a), this.setControl("mouseY", n);
|
|
});
|
|
}
|
|
/**
|
|
* Send a message to the audio thread (audio worket)
|
|
*/
|
|
send(a) {
|
|
W(a instanceof Object), this.audioWorklet && this.audioWorklet.port.postMessage(a);
|
|
}
|
|
async init() {
|
|
if (!this.audioCtx) {
|
|
if (W(!this.audioCtx), this.audioCtx = this.outputNode?.context || new AudioContext({
|
|
latencyHint: "interactive",
|
|
sampleRate: 48e3
|
|
}), await this.audioCtx.resume(), !this.audioCtx.audioWorklet)
|
|
throw new Error(
|
|
"Audio cannot be loaded: non-secure origin? (AudioContext.audioWorklet is undefined)"
|
|
);
|
|
await this.audioCtx.audioWorklet.addModule(ge), await this.audioCtx.audioWorklet.addModule(Ge), this.audioWorklet = new AudioWorkletNode(
|
|
this.audioCtx,
|
|
"sample-generator",
|
|
{
|
|
outputChannelCount: [2]
|
|
}
|
|
), this.audioWorklet.port.onmessage = (a) => {
|
|
const { id: n, time: t, type: s } = a.data;
|
|
s === "SIGNAL_TRIGGER" ? this.graph.dfs((o) => {
|
|
if (o.type === "signal" && o.id === n) {
|
|
const d = o.callback(t, n);
|
|
isNaN(d) ? d !== void 0 && console.warn(
|
|
`expected number from "on" callback with id "${n}", got "${d}" instead.`
|
|
) : window.postMessage({
|
|
type: "KABELSALAT_SET_CONTROL",
|
|
value: d,
|
|
id: n
|
|
});
|
|
}
|
|
return o;
|
|
}) : s === "STOP" ? setTimeout(() => this.destroy(), a.data.fadeTime * 1e3 + 200) : s === "SEND_SAMPLES" && this.graph.dfs((o) => (o.type !== "scope" || o.ins.length < 2 || o.ins[1].value !== n || window.postMessage({
|
|
type: "KABELSALAT_UPDATE_SCOPE",
|
|
samples: a.data.samples,
|
|
channels: a.data.channels,
|
|
channel: a.data.channel,
|
|
id: n
|
|
}), o));
|
|
}, this.recorder = new window.AudioWorkletNode(this.audioCtx, "recorder"), this.audioWorklet.connect(this.recorder), this.sendCustomUgens(), this.recorder.connect(this.outputNode || this.audioCtx.destination), this.recorder.port.onmessage = (a) => {
|
|
if (a.data.eventType === "data" && this.recordedBuffers.push(a.data.audioBuffer), a.data.eventType === "stop") {
|
|
console.log("recording stopped");
|
|
const n = ye(
|
|
this.recordedBuffers,
|
|
this.audioCtx.sampleRate,
|
|
2
|
|
);
|
|
Je(n, "kabelsalat.wav", "audio/wav"), this.recordedBuffers = [];
|
|
}
|
|
}, this.recordOnPlay && this.record();
|
|
}
|
|
}
|
|
destroy() {
|
|
this.audioWorklet?.disconnect(), this.audioWorklet = null, this.recorder?.disconnect(), this.recorder = null, !this.outputNode && this.audioCtx?.close(), this.audioCtx = null;
|
|
}
|
|
/**
|
|
* Stop audio playback
|
|
*/
|
|
stop() {
|
|
this.audioCtx && this.send({ type: "STOP" }), this.mouse?.detach();
|
|
}
|
|
record() {
|
|
if (!this.audioCtx) {
|
|
this.recordOnPlay = !0;
|
|
return;
|
|
}
|
|
this.recordedBuffers = [], this.recorder.parameters.get("isRecording").setValueAtTime(1, 0), console.log("recording started");
|
|
}
|
|
stopRecording() {
|
|
this.recordOnPlay = !1, this.audioCtx && this.recorder.parameters.get("isRecording").setValueAtTime(0, 0);
|
|
}
|
|
set fadeTime(a) {
|
|
this.send({ type: "FADE_TIME", fadeTime: a });
|
|
}
|
|
set maxUnits(a) {
|
|
this.send({ type: "MAX_UNITS", maxUnits: a });
|
|
}
|
|
}
|
|
function Je(e, a, n) {
|
|
const t = new Blob([e], { type: n }), s = document.createElement("a");
|
|
s.href = window.URL.createObjectURL(t), s.download = a, s.click();
|
|
}
|
|
let je = 0;
|
|
u(
|
|
"signal",
|
|
(e, a) => {
|
|
const n = je++, t = getNode("signal", e, n);
|
|
return t.callback = a, t.id = n, t;
|
|
},
|
|
{
|
|
ugen: "Signal",
|
|
compile: ({ vars: [e, a], ...n }) => w(n, e, a, "time")
|
|
}
|
|
);
|
|
let Qe = (e) => `sin(${e})`, Be = (e) => `cos(${e})`, Ee = (e) => `tan(${e})`, Oe = (e) => `asin(${e})`, De = (e) => `acos(${e})`, Ae = (e) => `atan(${e})`, N = (e, a, n) => `${e} = ${a};${n ? ` /* ${n} */` : ""}`, $e = (e, ...a) => {
|
|
if (a.unshift(`nodes[${e.ugenIndex}]`), e.ugen === "Sequence" || e.ugen === "Pick") {
|
|
const n = a.length - 2, t = `(float[${n}]){${a.slice(2).join(",")}}`;
|
|
return N(
|
|
e.name,
|
|
`${e.ugen}_update(${a[0]}, ${a[1]}, ${n}, ${t})`,
|
|
e.ugen
|
|
);
|
|
}
|
|
return N(e.name, `${e.ugen}_update(${a.join(",")})`, e.ugen);
|
|
}, qe = (e) => `pow(2.0, ((${e} - 69.0) / 12.0)) * 440.0`, _e = (e, a) => `pow(${e}, ${a})`, ea = (e) => `exp(${e})`, aa = (e) => `log(${e})`, na = (e, a) => `${e}>=${a}?${e}-${a}:${e}`, ta = (e) => `fabs(${e})`, ia = (e, a) => `fmin(${e}, ${a})`, sa = (e, a) => `fmax(${e}, ${a})`, la = (e) => `fround(${e})`, oa = (e) => `floor(${e})`, da = (e) => `ceil(${e})`, ca = (e, a) => `((pair) {${e}, ${a}})`, M = (e) => `${e}.a`, pa = (e) => `${e}.b`, ua = (e, a) => `(${M(e)} < ${M(a)} ? ${e} : ${a})`, ma = (e, a) => `(${M(e)} > ${M(a)} ? ${e} : ${a})`;
|
|
const ra = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
__proto__: null,
|
|
abs: ta,
|
|
ceil: da,
|
|
def: N,
|
|
defAcos: De,
|
|
defAsin: Oe,
|
|
defAtan: Ae,
|
|
defCos: Be,
|
|
defSin: Qe,
|
|
defTan: Ee,
|
|
defUgen: $e,
|
|
exp: ea,
|
|
floor: oa,
|
|
log: aa,
|
|
max: sa,
|
|
midinote: qe,
|
|
min: ia,
|
|
mod: na,
|
|
pair_a: M,
|
|
pair_a_max: ma,
|
|
pair_a_min: ua,
|
|
pair_b: pa,
|
|
pair_make: ca,
|
|
pow: _e,
|
|
round: la
|
|
}, Symbol.toStringTag, { value: "Module" })), i = {
|
|
js: Pe,
|
|
c: ra
|
|
}, E = (e, a) => l(e, {
|
|
ugen: a,
|
|
compile: ({ vars: n, ...t }) => i[t.lang].defUgen(t, ...n)
|
|
});
|
|
let ha = u("time", (e) => new c("time", e), {
|
|
tags: ["meta"],
|
|
description: "Returns elapsed time in seconds",
|
|
compile: ({ name: e, lang: a }) => i[a].def(e, "time")
|
|
}), ga = u(
|
|
"raw",
|
|
(e, a) => new c("raw", a).withIns(X(e)),
|
|
{
|
|
ins: [
|
|
{ name: "in" },
|
|
{
|
|
name: "code",
|
|
description: "expression with variable `t` being the elapsed time and `$input` the input."
|
|
}
|
|
],
|
|
tags: ["meta"],
|
|
description: "Raw code node, expects floats between -1 and 1",
|
|
compile: ({ vars: e, node: a, name: n }) => `let $input = ${e[0]};
|
|
const ${n} = (${a.value}); // raw`,
|
|
examples: [
|
|
`sine(4).range(.5,1)
|
|
.raw("(time*110%1*2-1)*$input")
|
|
.out()`
|
|
]
|
|
}
|
|
), Ga = u(
|
|
"bytebeat",
|
|
(e, a) => new c("bytebeat", a).withIns(X(e)),
|
|
{
|
|
ins: [
|
|
{ name: "t", description: "time in samples" },
|
|
{
|
|
name: "code",
|
|
description: "bytebeat code with variable `t`"
|
|
}
|
|
],
|
|
tags: ["meta"],
|
|
description: "Bytebeat node, expects numbers from 0 to 255",
|
|
examples: [
|
|
`time().mul(8000).bytebeat\`
|
|
// Fractalized Past
|
|
// by: lhphr
|
|
// from: https://dollchan.net/btb/res/3.html#69
|
|
|
|
(t>>10^t>>11)%5*((t>>14&3^t>>15&1)+1)*t%99+((3+(t>>14&3)-(t>>16&1))/3*t%99&64)
|
|
\`.out()`
|
|
],
|
|
compile: ({ vars: e, node: a, name: n }) => `let t = ${e[0]};
|
|
const ${n} = ((${a.value}) & 255) / 127.5 - 1; // bytebeat`
|
|
}
|
|
), ya = u(
|
|
"floatbeat",
|
|
(e, a) => new c("bytebeat", a).withIns(X(e)),
|
|
{
|
|
ins: [
|
|
{ name: "t", description: "time in samples" },
|
|
{
|
|
name: "code",
|
|
description: "floatbeat code with variable `t`"
|
|
}
|
|
],
|
|
tags: ["meta"],
|
|
description: "Raw code node, expects numbers from -1 to 1",
|
|
compile: ({ vars: e, node: a, name: n }) => `let t = ${e[0]}; const ${n} = (${a.value}); // floatbeat`
|
|
}
|
|
), Xa = l("adsr", {
|
|
ugen: "ADSRNode",
|
|
tags: ["envelope"],
|
|
description: "ADSR envelope",
|
|
examples: [
|
|
`impulse(1).perc(.5)
|
|
.adsr(.01, .1, .5, .1)
|
|
.mul(sine(220)).out()`
|
|
],
|
|
ins: [
|
|
{ name: "gate", default: 0, description: "gate input" },
|
|
{ name: "att", default: 0.02, description: "attack time" },
|
|
{ name: "dec", default: 0.1, description: "decay time" },
|
|
{ name: "sus", default: 0.2, description: "sustain level" },
|
|
{ name: "rel", default: 0.1, description: "release time" }
|
|
],
|
|
compile: ({
|
|
vars: [e = 0, a = 0.02, n = 0.1, t = 0.2, s = 0.1],
|
|
...o
|
|
}) => i[o.lang].defUgen(o, "time", e, a, n, t, s)
|
|
}), fa = y(
|
|
"ar",
|
|
(e = 0, a = 0.02, n = 0.1) => e.adsr(a, 0, 1, n),
|
|
{
|
|
tags: ["envelope"],
|
|
description: "AR envelope",
|
|
examples: ["impulse(1).ad(.01, .1).mul(sine(220)).out()"],
|
|
ins: [
|
|
{ name: "trig", default: 0, description: "gate input" },
|
|
{ name: "att", default: 0.02, description: "attack time" },
|
|
{ name: "rel", default: 0.1, description: "release time" }
|
|
]
|
|
}
|
|
), Za = y(
|
|
"ad",
|
|
(e = 0, a = 0.02, n = 0.1) => e.adsr(a, n, 0, n),
|
|
{
|
|
tags: ["envelope"],
|
|
description: "AD envelope",
|
|
examples: ["impulse(1).ad(.01, .1).mul(sine(220)).out()"],
|
|
ins: [
|
|
{ name: "trig", default: 0, description: "gate input" },
|
|
{ name: "att", default: 0.02, description: "attack time" },
|
|
{ name: "dec", default: 0.1, description: "decay time" }
|
|
]
|
|
}
|
|
), ba = l("clock", {
|
|
ugen: "Clock",
|
|
internal: !0,
|
|
// impulse is the preferred way..
|
|
tags: ["regular", "clock"],
|
|
description: "Clock source, with tempo in BPM",
|
|
examples: ["clock(120).clockdiv(16).mul(sine(220)).out()"],
|
|
ins: [
|
|
{
|
|
name: "bpm",
|
|
default: 120,
|
|
description: "clock tempo in bpm (beats per minute)"
|
|
}
|
|
],
|
|
compile: ({ vars: [e = 120], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), xa = l("clockdiv", {
|
|
ugen: "ClockDiv",
|
|
tags: ["clock", "trigger"],
|
|
description: "Clock signal divider",
|
|
examples: ["impulse(8).clockdiv(2).ad(.1,.1).mul(sine(220)).out()"],
|
|
ins: [
|
|
{ name: "clock", default: 0, description: "clock input" },
|
|
{ name: "divisor", default: 2, description: "tempo divisor" }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 2], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), Ra = l("distort", {
|
|
ugen: "Distort",
|
|
tags: ["fx", "distortion"],
|
|
description: "Overdrive-style distortion",
|
|
examples: [
|
|
`sine(220)
|
|
.distort( saw(.5).range(0,1) )
|
|
.out()`
|
|
],
|
|
ins: [
|
|
{ name: "in", default: 0 },
|
|
{ name: "amt", default: 0, description: "distortion amount" }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), O = l("noise", {
|
|
ugen: "NoiseOsc",
|
|
tags: ["source", "noise"],
|
|
description: "White noise source",
|
|
examples: ["noise().mul(.25).out()"],
|
|
ins: [
|
|
{
|
|
name: "next",
|
|
default: 1,
|
|
description: "if 0, the noise will hold the previous value. defaults to 1."
|
|
}
|
|
],
|
|
compile: ({ lang: e, vars: [a = 1], ...n }) => i[e].defUgen(n, a)
|
|
}), La = l("lcgnoise", {
|
|
ugen: "LcgNoise",
|
|
tags: ["source", "noise"],
|
|
description: "Lcg white noise source.",
|
|
examples: ["lcgnoise().mul(.25).out()"],
|
|
ins: [
|
|
{
|
|
name: "next",
|
|
default: 1,
|
|
description: "if 0, the noise will hold the previous value. defaults to 1."
|
|
},
|
|
{
|
|
name: "reset",
|
|
default: 0,
|
|
description: "if 1, the random number generator sequence will reset."
|
|
}
|
|
],
|
|
compile: ({ lang: e, vars: [a = 1, n = 0], ...t }) => i[e].defUgen(t, a, n)
|
|
}), Ma = l("pink", {
|
|
ugen: "PinkNoise",
|
|
tags: ["source", "noise"],
|
|
description: "Pink noise source",
|
|
examples: ["pink().mul(.5).out()"],
|
|
ins: [],
|
|
compile: ({ lang: e, ...a }) => i[e].defUgen(a)
|
|
}), za = l("brown", {
|
|
ugen: "BrownNoiseOsc",
|
|
tags: ["source", "noise"],
|
|
description: "Brown noise source",
|
|
examples: ["brown().out()"],
|
|
ins: [],
|
|
compile: ({ lang: e, ...a }) => i[e].defUgen(a)
|
|
}), Va = l("dust", {
|
|
ugen: "DustOsc",
|
|
tags: ["trigger", "noise", "source"],
|
|
description: "Generates random impulses from 0 to +1.",
|
|
examples: ["dust(200).out()"],
|
|
ins: [
|
|
{ name: "density", default: 0, description: "average impulses per second" }
|
|
],
|
|
compile: ({ vars: [e = 0], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), D = l("impulse", {
|
|
ugen: "ImpulseOsc",
|
|
tags: ["regular", "trigger"],
|
|
description: "Regular single sample impulses (0 - 1)",
|
|
examples: ["impulse(10).out()"],
|
|
ins: [
|
|
{ name: "freq", default: 0 },
|
|
{ name: "phase", default: 0 }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), Wa = l("saw", {
|
|
ugen: "SawOsc",
|
|
tags: ["regular", "waveform", "source"],
|
|
description: "Sawtooth wave oscillator with anti aliasing",
|
|
examples: ["saw(110).mul(.5).out()"],
|
|
ins: [{ name: "freq", default: 0 }],
|
|
compile: ({ vars: [e = 0], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), Ya = l("zaw", {
|
|
ugen: "ZawOsc",
|
|
tags: ["regular", "waveform", "source"],
|
|
description: "Sawtooth wave oscillator with sharp edges. Use saw for anti aliased variant.",
|
|
examples: ["zaw(110).mul(.5).out()"],
|
|
ins: [{ name: "freq", default: 0 }],
|
|
compile: ({ vars: [e = 0], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), Na = l("sine", {
|
|
tags: ["regular", "waveform", "source"],
|
|
ugen: "SineOsc",
|
|
description: "Sine wave oscillator",
|
|
examples: ["sine(220).out()"],
|
|
ins: [
|
|
{ name: "freq", default: 0 },
|
|
{ name: "sync", default: 0, description: "sync input" },
|
|
{ name: "phase", default: 0, description: "phase offset" }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0, n = 0], ...t }) => i[t.lang].defUgen(t, e, a, n)
|
|
}), Ha = l("tri", {
|
|
ugen: "TriOsc",
|
|
tags: ["regular", "waveform", "source"],
|
|
description: "Triangle wave oscillator",
|
|
examples: ["tri(220).out()"],
|
|
ins: [{ name: "freq", default: 0 }],
|
|
compile: ({ vars: [e = 0], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), Sa = l("pulse", {
|
|
ugen: "PulseOsc",
|
|
tags: ["regular", "waveform", "source"],
|
|
description: "Pulse wave oscillator",
|
|
examples: ["pulse(220, sine(.1).range(.1,.5)).mul(.5).out()"],
|
|
ins: [
|
|
{ name: "freq", default: 0 },
|
|
{ name: "pw", default: 0.5, description: "pulse width 0 - 1" }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0.5], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), Ta = l("slide", {
|
|
ugen: "Slide",
|
|
tags: ["fx"],
|
|
internal: !0,
|
|
description: "Slide/portamento node",
|
|
examples: [
|
|
`impulse(2).seq(55,110,220,330)
|
|
.slide(4).sine().out()`
|
|
],
|
|
ins: [
|
|
{ name: "in", default: 0 },
|
|
{ name: "rate", default: 1 }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 1], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), wa = l("lag", {
|
|
ugen: "Lag",
|
|
tags: ["fx"],
|
|
description: "Smoothes a signal. Good for slide / portamento effects.",
|
|
examples: [
|
|
`impulse(2).seq(220,330,440,550)
|
|
.lag(.4).sine().out()`
|
|
],
|
|
ins: [
|
|
{ name: "in", default: 0 },
|
|
{ name: "rate", default: 1, description: "60 dB lag time in seconds" }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 1], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), va = l("slew", {
|
|
ugen: "Slew",
|
|
tags: ["fx"],
|
|
description: "Limits the slope of an input signal. The slope is expressed in units per second.",
|
|
examples: ["pulse(800).slew(4000, 4000).out()"],
|
|
ins: [
|
|
{ name: "in", default: 0 },
|
|
{
|
|
name: "up",
|
|
default: 1,
|
|
description: "Maximum upward slope in units per second"
|
|
},
|
|
{
|
|
name: "dn",
|
|
default: 1,
|
|
description: "Maximum downward slope in units per second"
|
|
}
|
|
],
|
|
compile: ({ vars: [e = 0, a = 1, n = 1], ...t }) => i[t.lang].defUgen(t, e, a, n)
|
|
}), A = l("filter", {
|
|
ugen: "Filter",
|
|
tags: ["fx", "filter"],
|
|
internal: !0,
|
|
description: "Two-pole low-pass filter",
|
|
examples: ["saw(55).lpf( sine(1).range(.4,.8) ).out()"],
|
|
ins: [
|
|
{ name: "in", default: 0 },
|
|
{ name: "cutoff", default: 1 },
|
|
{ name: "reso", default: 0 }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 1, n = 0], ...t }) => i[t.lang].defUgen(t, e, a, n)
|
|
}), Ka = l("fold", {
|
|
ugen: "Fold",
|
|
tags: ["fx", "distortion", "limiter"],
|
|
description: 'Distort incoming audio signal by "folding"',
|
|
examples: [
|
|
`sine(55)
|
|
.fold( sine(.5).range(0.2,4) )
|
|
.out()`
|
|
],
|
|
ins: [
|
|
{ name: "in", default: 0 },
|
|
{ name: "rate", default: 0 }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), Ca = l("seq", {
|
|
ugen: "Sequence",
|
|
tags: ["sequencer"],
|
|
description: "Trigger controlled sequencer",
|
|
examples: [
|
|
`impulse(2).seq(220,330,440,550)
|
|
.sine().out()`
|
|
],
|
|
ins: [
|
|
{ name: "trig", default: 0 },
|
|
{ name: "step", default: 0, dynamic: !0, description: "step inputs" }
|
|
// 1-Infinity of steps
|
|
],
|
|
compile: ({ vars: e, ...a }) => i[a.lang].defUgen(a, ...e)
|
|
}), Ia = l("delay", {
|
|
ugen: "Delay",
|
|
tags: ["fx"],
|
|
description: "Delay line node",
|
|
examples: [
|
|
`impulse(1).ad(.01,.2).mul(sine(220))
|
|
.add(x=>x.delay(.1).mul(.8)).out()`
|
|
],
|
|
ins: [
|
|
{ name: "in", default: 0 },
|
|
{ name: "time", default: 0 }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), Ua = l("hold", {
|
|
ugen: "Hold",
|
|
tags: ["fx"],
|
|
description: "Sample and hold",
|
|
examples: [
|
|
`noise().hold(impulse(2))
|
|
.range(220,880).sine().out()`
|
|
],
|
|
ins: [
|
|
{ name: "in", default: 0 },
|
|
{ name: "trig", default: 0 }
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), ka = l("midifreq", {
|
|
ugen: "MidiFreq",
|
|
tags: ["external", "midi"],
|
|
description: "Outputs frequency of midi note in. Multiple instances will do voice allocation",
|
|
examples: ["midifreq().sine().out()"],
|
|
ins: [
|
|
{
|
|
name: "channel",
|
|
default: -1,
|
|
description: "Channel filter. Defaults to all channels"
|
|
}
|
|
],
|
|
compile: ({ vars: [e = -1], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), Pa = l("midigate", {
|
|
ugen: "MidiGate",
|
|
tags: ["external", "midi"],
|
|
description: "outputs gate of midi note in. Multiple instances will do voice allocation",
|
|
examples: ["midigate().lag(1).mul(sine(220)).out()"],
|
|
ins: [{ name: "channel", default: -1 }],
|
|
compile: ({ vars: [e = -1], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), Fa = l("midivel", {
|
|
ugen: "MidiVel",
|
|
tags: ["external", "midi"],
|
|
description: "outputs velocity of midi note in. Multiple instances will do voice allocation",
|
|
examples: [
|
|
"midigate().ar(0.01,0.2).mul(saw(midifreq())).mul(midivel()).mul(.8).out()"
|
|
],
|
|
ins: [{ name: "channel", default: -1 }],
|
|
compile: ({ vars: [e = -1], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), Ja = l("midicc", {
|
|
ugen: "MidiCC",
|
|
tags: ["external", "midi"],
|
|
description: "Outputs bipolar value of given midi cc number. initValue can be set to be the output before getting first cc message.",
|
|
examples: ["midicc(74).range(100,200).sine().out()"],
|
|
ins: [
|
|
{ name: "ccnumber", default: -1 },
|
|
{ name: "channel", default: -1 },
|
|
{ name: "initValue", default: -1 }
|
|
// could not name it "default" because syntax error
|
|
],
|
|
compile: ({ vars: [e = -1, a = -1], ...n }) => i[n.lang].defUgen(n, e, a)
|
|
}), v = l("cc", {
|
|
ugen: "CC",
|
|
tags: ["external"],
|
|
description: "CC control",
|
|
ins: [
|
|
{ name: "id", default: 0 },
|
|
{ name: "value", default: 0 }
|
|
],
|
|
compile: ({ vars: [e], ...a }) => i[a.lang].defUgen(a, e)
|
|
}), ja = l("audioin", {
|
|
ugen: "AudioIn",
|
|
tags: ["source", "external"],
|
|
description: "External Audio Input, depends on your system input",
|
|
examples: ["audioin().add(x=>x.delay(.1).mul(.8)).out()"],
|
|
ins: [],
|
|
compile: (e) => i[e.lang].defUgen(e, "input")
|
|
}), H = l("log", {
|
|
tags: ["math"],
|
|
description: "calculates the logarithm (base 10) of the input signal",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].log(e))
|
|
}), $ = l("exp", {
|
|
tags: ["math"],
|
|
description: "raises e to the power of the input signal",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].exp(e))
|
|
}), Qa = l("pow", {
|
|
tags: ["math"],
|
|
description: "raises the input to the given power",
|
|
ins: [{ name: "in" }, { name: "power" }],
|
|
compile: ({ vars: [e = 0, a = 1], name: n, lang: t }) => i[t].def(n, i[t].pow(e, a))
|
|
}), q = l("sin", {
|
|
tags: ["math"],
|
|
description: "calculates the sine of the input signal",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].defSin(e))
|
|
}), _ = l("cos", {
|
|
tags: ["math"],
|
|
description: "calculates the cosine of the input signal",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].defCos(e))
|
|
}), Ba = l("tan", {
|
|
tags: ["math"],
|
|
description: "calculates the tan of the input signal",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].defTan(e))
|
|
}), Ea = l("acos", {
|
|
tags: ["math"],
|
|
description: "calculates the acos of the input signal",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].defAcos(e))
|
|
}), Oa = l("asin", {
|
|
tags: ["math"],
|
|
description: "calculates the asin of the input signal",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].defAsin(e))
|
|
}), Da = l("atan", {
|
|
tags: ["math"],
|
|
description: "calculates the atan of the input signal",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].defAtan(e))
|
|
}), Aa = l("mul", {
|
|
tags: ["math"],
|
|
description: "Multiplies the given signals.",
|
|
examples: ["sine(220).mul( sine(4).range(.25,1) ).out()"],
|
|
ins: [{ name: "in", dynamic: !0 }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(a, e.join(" * ") || 0)
|
|
}), K = l("add", {
|
|
tags: ["math"],
|
|
description: "sums the given signals",
|
|
examples: ["n([0,3,7,10]).add(60).midinote().sine().mix(2).out()"],
|
|
ins: [{ name: "in", dynamic: !0 }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(a, e.join(" + ") || 0)
|
|
}), $a = l("div", {
|
|
tags: ["math"],
|
|
description: "adds the given signals",
|
|
ins: [{ name: "in", dynamic: !0 }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(a, e.join(" / ") || 0)
|
|
}), qa = l("sub", {
|
|
tags: ["math"],
|
|
description: "subtracts the given signals",
|
|
ins: [{ name: "in", dynamic: !0 }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(a, e.join(" - ") || 0)
|
|
}), _a = l("mod", {
|
|
tags: ["math"],
|
|
description: "calculates the modulo",
|
|
examples: ["add(x=>x.add(.003).mod(1)).out()"],
|
|
ins: [{ name: "in" }, { name: "modulo" }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(a, i[n].mod(...e) || 0)
|
|
}), en = l("abs", {
|
|
tags: ["math"],
|
|
description: "returns the absolute value of the signal",
|
|
ins: [{ name: "in" }],
|
|
examples: ["sine(440).abs().out()"],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].abs(e))
|
|
}), an = l("round", {
|
|
tags: ["math"],
|
|
description: "Rounds the signal to the nearest integer",
|
|
ins: [{ name: "in" }],
|
|
examples: ["sine(440.5).round().out()"],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].round(e))
|
|
}), nn = l("clamp", {
|
|
tags: ["math"],
|
|
description: "Clamps the signal to stay within the given range",
|
|
ins: [{ name: "in" }, { name: "min" }, { name: "max" }],
|
|
examples: ["sine(440.5).clamp(-.6,.6).out()"],
|
|
compile: ({ vars: [e = 0, a = -1, n = 1], name: t, lang: s }) => {
|
|
const o = i[s].min(a, n), d = i[s].max(a, n), G = i[s].min(i[s].max(e, o), d);
|
|
return i[s].def(t, G);
|
|
}
|
|
}), tn = l("floor", {
|
|
tags: ["math"],
|
|
description: "Rounds the signal down",
|
|
ins: [{ name: "in" }],
|
|
examples: ["sine(440.5).floor().out()"],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].floor(e))
|
|
}), sn = l("ceil", {
|
|
tags: ["math"],
|
|
description: "Rounds the signal up",
|
|
ins: [{ name: "in" }],
|
|
examples: ["sine(440.5).ceil().out()"],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].ceil(e))
|
|
}), ln = l("sign", {
|
|
tags: ["math"],
|
|
description: "Returns 1 if positive and -1 if negative. uses Math.sign",
|
|
ins: [{ name: "in" }],
|
|
examples: ["sine(440.5).ceil().out()"],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, i[n].sign(e))
|
|
}), on = l("min", {
|
|
tags: ["math"],
|
|
description: "returns the minimum of the given signals",
|
|
examples: [
|
|
"impulse(4).apply(x => min(x.seq(0,3,2), x.seq(0,7,0,5,0)).add(48).midinote().sine()).out()"
|
|
],
|
|
ins: [{ name: "in", dynamic: !0 }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(a, e.reduce(i[n].min) || 0)
|
|
}), dn = l("max", {
|
|
tags: ["math"],
|
|
description: "returns the maximum of the given signals",
|
|
examples: [
|
|
"impulse(4).apply(x => max(x.seq(0,3,2), x.seq(0,7,0,5,0)).add(48).midinote().sine()).out()"
|
|
],
|
|
ins: [{ name: "in", dynamic: !0 }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(a, e.reduce(i[n].max) || 0)
|
|
}), cn = l("argmin", {
|
|
tags: ["math"],
|
|
description: "returns the index of the minimum of the given signals",
|
|
examples: [
|
|
"argmin(saw(1), saw(3), saw(5)).mul(12).add(48).midinote().sine().out()"
|
|
],
|
|
ins: [{ name: "in", dynamic: !0 }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(
|
|
a,
|
|
i[n].pair_b(
|
|
e.map(i[n].pair_make).reduce(i[n].pair_a_min)
|
|
) || 0
|
|
)
|
|
}), pn = l("argmax", {
|
|
tags: ["math"],
|
|
description: "returns the index of the maximum of the given signals",
|
|
examples: [
|
|
"argmax(saw(1), saw(3), saw(5)).mul(12).add(48).midinote().sine().out()"
|
|
],
|
|
ins: [{ name: "in", dynamic: !0 }],
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(
|
|
a,
|
|
i[n].pair_b(
|
|
e.map(i[n].pair_make).reduce(i[n].pair_a_max)
|
|
) || 0
|
|
)
|
|
}), ee = l("greater", {
|
|
tags: ["logic"],
|
|
description: "returns 1 if input is greater then threshold",
|
|
ins: [{ name: "in" }, { name: "threshold" }],
|
|
examples: [
|
|
`greater(sine(1),0)
|
|
.bipolar().range(100,200)
|
|
.sine().out()`
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0], name: n, lang: t }) => i[t].def(n, `${e} > ${a}`)
|
|
}), ae = l("lower", {
|
|
tags: ["logic"],
|
|
description: "returns 1 if input is lower then threshold",
|
|
ins: [{ name: "in" }, { name: "threshold" }],
|
|
examples: [
|
|
`lower(sine(1),0)
|
|
.bipolar().range(100,200)
|
|
.sine().out()`
|
|
],
|
|
compile: ({ vars: [e = 0, a = 0], name: n, lang: t }) => i[t].def(n, `${e} < ${a}`)
|
|
}), un = ee, mn = ae, rn = l("xor", {
|
|
tags: ["logic"],
|
|
description: "returns 1 if exactly one of the inputs is 1",
|
|
ins: [{ name: "a" }, { name: "b" }],
|
|
compile: ({ vars: [e = 0, a = 0], name: n, lang: t }) => i[t].def(n, `${e} != ${a} ? 1 : 0`)
|
|
}), hn = l("and", {
|
|
tags: ["logic"],
|
|
description: "returns 1 if both inputs are 1",
|
|
ins: [{ name: "a" }, { name: "b" }],
|
|
compile: ({ vars: [e = 0, a = 0], name: n, lang: t }) => i[t].def(n, `${e} && ${a} ? 1 : 0`)
|
|
}), gn = l("or", {
|
|
tags: ["logic"],
|
|
description: "returns 1 if one or both inputs are 1",
|
|
ins: [{ name: "a" }, { name: "b" }],
|
|
compile: ({ vars: [e = 0, a = 0], name: n, lang: t }) => i[t].def(n, `${e} || ${a} ? 1 : 0`)
|
|
}), Gn = l("not", {
|
|
tags: ["logic"],
|
|
description: "returns 1 if input is 0, otherwise 0",
|
|
ins: [{ name: "in" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, `(${e} === 0 ? 1 : 0)`)
|
|
}), yn = l("bool", {
|
|
tags: ["logic"],
|
|
description: "returns 1 signal is non zero. inspired by genish",
|
|
ins: [{ name: "a" }],
|
|
compile: ({ vars: [e = 0], name: a, lang: n }) => i[n].def(a, `(${e} === 0 ? 0 : 1)`)
|
|
}), Xn = l("ifelse", {
|
|
tags: ["logic"],
|
|
description: "if control is 1, a is returned, otherwise b",
|
|
ins: [{ name: "control" }, { name: "a" }, { name: "b" }],
|
|
compile: ({ vars: [e = 0, a = 0, n = 0], name: t, lang: s }) => i[s].def(t, `(${e} === 1 ? ${a} : ${n})`),
|
|
examples: ["ifelse(pulse(1), sine(220), sine(330)).out()"]
|
|
}), fn = l("range", {
|
|
tags: ["math"],
|
|
description: "Scales the incoming bipolar value to the given range.",
|
|
examples: ["sine(.5).range(.25,1).mul(sine(440)).out()"],
|
|
ins: [{ name: "in" }, { name: "min" }, { name: "max" }],
|
|
compile: ({ vars: e, name: a, lang: n }) => {
|
|
const [t, s, o, d = 1] = e, G = `((${t} + 1) * 0.5)`, p = d === 1 ? G : i[n].pow(G, d);
|
|
return i[n].def(a, `${p} * (${o} - ${s}) + ${s}`);
|
|
}
|
|
}), Zn = l("remap", {
|
|
ugen: "Remap",
|
|
tags: ["math"],
|
|
description: "Remaps input from one value range to another",
|
|
ins: [
|
|
{ name: "in" },
|
|
{ name: "inmin" },
|
|
{ name: "inmax" },
|
|
{ name: "outmin" },
|
|
{ name: "outmax" }
|
|
],
|
|
// examples: [`sine(440).abs().out()`],
|
|
compile: ({
|
|
vars: [e = 0, a = -1, n = 1, t = -1, s = 1],
|
|
...o
|
|
}) => i[o.lang].defUgen(o, e, a, n, t, s)
|
|
}), bn = l("thru", {
|
|
compile: ({ name: e, vars: a, lang: n }) => i[n].def(e, a[0], "thru")
|
|
}), xn = y(
|
|
"rangex",
|
|
(e, a, n) => {
|
|
let t = H(a), s = H(n).sub(t), o = e.unipolar().mul(s).add(t);
|
|
return $(o);
|
|
},
|
|
{
|
|
tags: ["math"],
|
|
description: "exponential range",
|
|
ins: [{ name: "in" }, { name: "min" }, { name: "max" }],
|
|
examples: ["sine([1,3]).rangex(100, 2e3).sine().out()"]
|
|
}
|
|
), Rn = l("midinote", {
|
|
compile: ({ vars: [e], name: a, lang: n }) => i[n].def(a, i[n].midinote(e)),
|
|
tags: ["math"],
|
|
description: "convert midi number to frequency",
|
|
ins: [{ name: "midi" }],
|
|
examples: [
|
|
`impulse(4).seq(0,3,7,12).add(60)
|
|
.midinote().sine().out()`
|
|
]
|
|
}), Ln = l("src", {
|
|
internal: !0,
|
|
compile: ({ vars: [e = 0], name: a, lang: n, ...t }) => i[n].def(a, t.getSource(e), `read source ${e}`)
|
|
}), Mn = l("output", {
|
|
internal: !0,
|
|
ugen: "Output",
|
|
compile: ({ vars: [e, a = 0], name: n, lang: t, ...s }) => {
|
|
const o = s.getOutput(a), d = s.getSource(a);
|
|
return [
|
|
i[t].def(o, [o, e].join(" + "), `+ output ${a}`),
|
|
i[t].def(d, o, `write source ${a}`)
|
|
].join(`
|
|
`);
|
|
}
|
|
}), ne = l("poly"), te = X(Math.PI), zn = u(
|
|
"fork",
|
|
(e, a = 1) => ne(...Array.from({ length: a }, () => e.clone())),
|
|
{
|
|
ins: [{ name: "in" }, { name: "times" }],
|
|
tags: ["multi-channel"],
|
|
description: "split the signal into n channels",
|
|
examples: ["dust(4).fork(2).adsr(.1).mul(sine(220)).out()"]
|
|
}
|
|
), Vn = y("perc", (e, a) => e.adsr(0, 0, 1, a), {
|
|
tags: ["envelope"],
|
|
description: "percussive envelope. usable with triggers or gates",
|
|
ins: [{ name: "gate" }, { name: "release" }],
|
|
examples: ["impulse(4).perc(.1).mul( pink() ).out()"]
|
|
}), Wn = y(
|
|
"hpf",
|
|
(e, a, n = 0) => e.sub(e.lpf(a, n)),
|
|
{
|
|
ins: [{ name: "in" }, { name: "cutoff" }, { name: "reso" }],
|
|
description: "high pass filter",
|
|
tags: ["fx", "filter"],
|
|
examples: ["tri([220,331,442]).mix().hpf(sine(.5).range(0,.9)).out()"]
|
|
}
|
|
), Yn = y("lpf", A, {
|
|
ins: [{ name: "in" }, { name: "cutoff" }, { name: "reso" }],
|
|
description: "low pass filter",
|
|
tags: ["fx", "filter"],
|
|
examples: ["saw(55).lpf( sine(1).range(.4,.8) ).out()"]
|
|
}), Nn = l("bpf", {
|
|
ugen: "BPF",
|
|
ins: [{ name: "in" }, { name: "cutoff" }, { name: "reso" }],
|
|
description: "high pass filter",
|
|
tags: ["fx", "filter"],
|
|
compile: ({ vars: [e = 0, a = 1, n = 0], ...t }) => i[t.lang].defUgen(t, e, a, n)
|
|
}), Hn = y("lfnoise", (e) => O().hold(D(e)), {
|
|
ins: [{ name: "freq" }],
|
|
description: "low frequency stepped noise.",
|
|
tags: ["regular", "noise"],
|
|
examples: ["lfnoise(4).range(200,800).sine().out()"]
|
|
}), Sn = y(
|
|
"bipolar",
|
|
(e) => X(e).mul(2).sub(1),
|
|
{
|
|
ins: [{ name: "in" }],
|
|
description: "convert unipolar [0,1] signal to bipolar [-1,1]",
|
|
tags: ["math"]
|
|
// examples: [], // tbd
|
|
}
|
|
), Tn = y(
|
|
"unipolar",
|
|
(e) => X(e).add(1).div(2),
|
|
{
|
|
ins: [{ name: "in" }],
|
|
description: "convert bipolar [-1,1] signal to unipolar [0,1]",
|
|
tags: ["math"]
|
|
// examples: [], // tbd
|
|
}
|
|
), wn = y(
|
|
"pan",
|
|
(e, a) => (a = X(a).add(1).mul(te, 0.25), e.mul([_(a), q(a)])),
|
|
{
|
|
ins: [
|
|
{ name: "in" },
|
|
{
|
|
name: "pos",
|
|
description: "bipolar position: -1 = left, 0 = center, 1 = right"
|
|
}
|
|
],
|
|
description: "pans signal to stereo position. splits signal path in 2",
|
|
tags: ["multi-channel"],
|
|
examples: ["sine(220).pan(sine(.25)).out()"]
|
|
}
|
|
), vn = l("pick", {
|
|
tags: ["multi-channel"],
|
|
ugen: "Pick",
|
|
description: "Pick",
|
|
ins: [{ name: "index" }, { name: "inputs", dynamic: !0 }],
|
|
description: "picks input of given index",
|
|
examples: [
|
|
`sine(.25).range(0,2).round()
|
|
.pick(...sine([220,330,440]).ins)
|
|
.out()`
|
|
],
|
|
compile: ({ vars: e, ...a }) => i[a.lang].defUgen(a, ...e)
|
|
}), Kn = l("clip", {
|
|
tags: ["fx"],
|
|
ugen: "Clip",
|
|
description: "Hard limits the signal between lo and hi.",
|
|
ins: [{ name: "input" }, { name: "lo" }, { name: "hi" }],
|
|
compile: ({ vars: [e = 0, a = -1, n = 1], ...t }) => i[t.lang].defUgen(t, e, a, n)
|
|
}), Cn = l("trig", {
|
|
tags: ["trigger"],
|
|
ugen: "Trig",
|
|
description: "Emits a trigger impulse whenever the signal becomes positive. Useful to turn gates into triggers.",
|
|
ins: [
|
|
{ name: "input", default: 0 },
|
|
{ name: "lo", default: -1 },
|
|
{ name: "hi", default: 1 }
|
|
],
|
|
compile: ({ vars: [e = 0, a = -1, n = 1], ...t }) => i[t.lang].defUgen(t, e, a, n),
|
|
examples: [
|
|
`pulse(2)
|
|
.trig() // comment out to hear difference
|
|
.ar(.01,.2)
|
|
.mul(sine(200)).out()`
|
|
]
|
|
}), In = l("qf", {
|
|
tags: ["fx", "filter"],
|
|
ugen: "BiquadFilter",
|
|
description: "biQuad Filter.",
|
|
ins: [
|
|
{ name: "input", default: 0 },
|
|
{
|
|
name: "type",
|
|
default: 0,
|
|
description: "filter type: 0 = lowpass, 1 = highpass, 2 = band pass, 3 = notch, 4 = allpass, 5 = peaking, 6 = lowshelf, 7 = highshelf"
|
|
},
|
|
{ name: "freq", default: 500, description: "filter cutoff in Hz" },
|
|
{ name: "q", default: 1, description: "q factor" },
|
|
{ name: "gain", default: 1 }
|
|
],
|
|
compile: ({ vars: e, ...a }) => i[a.lang].defUgen(a, ...e),
|
|
examples: [
|
|
`pink()
|
|
.qf(
|
|
impulse(.5).seq(0,1,2,3,4,5,6,7), // type
|
|
tri(0.5).rangex(100, 8000), // freq
|
|
10, // Q
|
|
1, // gain (only relevant for types 5-7)
|
|
).div(4).out();`
|
|
]
|
|
}), Un = u(
|
|
"qlpf",
|
|
(e, a, n = 10) => e.qf(0, a, n),
|
|
{
|
|
description: "biQuad Low Pass Filter",
|
|
ins: [
|
|
{ name: "input" },
|
|
{ name: "freq" },
|
|
{ name: "q", description: "resonance" }
|
|
],
|
|
tags: ["fx", "filter"],
|
|
examples: [
|
|
`pink().qlpf(
|
|
tri(0.5).rangex(100, 8000), // cutoff freq
|
|
10 // Q
|
|
).out()`
|
|
]
|
|
}
|
|
), kn = u(
|
|
"qhpf",
|
|
(e, a, n = 10) => e.qf(1, a, n),
|
|
{
|
|
description: "biQuad High pass filter",
|
|
ins: [
|
|
{ name: "input" },
|
|
{ name: "freq" },
|
|
{ name: "q", description: "resonance" }
|
|
],
|
|
tags: ["fx", "filter"],
|
|
examples: [
|
|
`pink().qhpf(
|
|
tri(0.5).rangex(100, 8000), // cutoff freq
|
|
10 // Q
|
|
).out()`
|
|
]
|
|
}
|
|
), Pn = u(
|
|
"qbpf",
|
|
(e, a, n = 10) => e.qf(2, a, n),
|
|
{
|
|
description: "biQuad Band Pass Filter",
|
|
ins: [
|
|
{ name: "input" },
|
|
{ name: "freq" },
|
|
{ name: "q", description: "resonance" }
|
|
],
|
|
tags: ["fx", "filter"],
|
|
examples: [
|
|
`pink().qbpf(
|
|
tri(0.5).rangex(100, 8000), // cutoff freq
|
|
10 // Q
|
|
).out()`
|
|
]
|
|
}
|
|
), Fn = u(
|
|
"qnf",
|
|
(e, a, n = 10) => e.qf(3, a, n),
|
|
{
|
|
description: "biQuad Notch Filter",
|
|
ins: [
|
|
{ name: "input" },
|
|
{ name: "freq" },
|
|
{ name: "q", description: "resonance" }
|
|
],
|
|
tags: ["fx", "filter"],
|
|
examples: [
|
|
`pink().qnf(
|
|
tri(0.5).rangex(100, 8000), // cutoff freq
|
|
10 // Q
|
|
).out()`
|
|
]
|
|
}
|
|
), Jn = u(
|
|
"qapf",
|
|
(e, a, n = 10) => e.qf(3, a, n),
|
|
{
|
|
description: "biQuad All Pass Filter",
|
|
ins: [
|
|
{ name: "input" },
|
|
{ name: "freq" },
|
|
{ name: "q", description: "resonance" }
|
|
],
|
|
tags: ["fx", "filter"],
|
|
examples: [
|
|
`impulse(1).qapf(
|
|
tri(0.5).rangex(100, 8000), // cutoff freq
|
|
10 // Q
|
|
).out()`
|
|
]
|
|
}
|
|
), jn = u(
|
|
"split",
|
|
(e, a) => e.type !== "poly" ? a([e]) : a(e.ins),
|
|
{
|
|
ins: [{ name: "input" }, { name: "fn" }],
|
|
tags: ["multi-channel"],
|
|
description: "apply fn to an array of signals, one for each channel in input",
|
|
examples: ["sine([220,330,550]).split(chs => add(...chs)).out()"]
|
|
}
|
|
), Qn = u(
|
|
"mix",
|
|
(e, a = 1) => {
|
|
if ([1, 2].includes(a) || (a = 2, console.warn("mix only supports 1 or 2 channels atm.. falling back to 2")), e.type !== "poly")
|
|
return e;
|
|
if (a === 2) {
|
|
const n = e.ins.map((t, s, o) => {
|
|
const d = (s / (o.length - 1) * 2 - 1 + 1) * Math.PI / 4;
|
|
return t.mul([Math.cos(d), Math.sin(d)]).inherit(e);
|
|
});
|
|
return K(...n);
|
|
}
|
|
return e.ins = e.ins.map((n) => n.inherit(e)), x("mix").withIns(...e.ins);
|
|
},
|
|
{
|
|
compile: ({ vars: e, name: a, lang: n }) => i[n].def(a, `(${e.join(" + ")})`),
|
|
description: `mixes down multiple channels. Useful to make sure you get a mono or stereo signal out at the end.
|
|
When mixing down to 2 channels, the input channels are equally distributed over the stereo image, e.g. 3 channels are panned [-1,0,1]`,
|
|
ins: [
|
|
{ name: "in" },
|
|
{
|
|
name: "channels",
|
|
default: 1,
|
|
description: "how many channels to mix down to. Only supports 1 and 2"
|
|
}
|
|
],
|
|
tags: ["multi-channel"],
|
|
examples: ["sine([220,330,440]).mix(2).out()"]
|
|
}
|
|
);
|
|
c.prototype.feedback = function(e) {
|
|
return this.add(e);
|
|
};
|
|
let Bn = (e) => K(e), En = X, On = X, Dn = y("mouseX", () => v("mouseX"), {
|
|
ins: [],
|
|
description: "X position of mouse, bipolar range",
|
|
tags: ["external"],
|
|
examples: ["mouseX.range(100,800).sine().out()"]
|
|
}), An = Dn(), $n = y("mouseY", () => v("mouseY"), {
|
|
ins: [],
|
|
description: "Y position of mouse, bipolar range",
|
|
tags: ["external"],
|
|
examples: ["mouseY.range(800,100).sine().out()"]
|
|
}), qn = $n(), _n = u(
|
|
"scope",
|
|
(e, a) => {
|
|
let n = 1;
|
|
e.type === "poly" && (n = e.ins.length);
|
|
const t = getNode("scope", e, a, n);
|
|
return t.type !== "poly" ? (t.ins.push({ type: "n", value: 0, ins: [] }), t) : (t.ins.forEach((s, o) => s.ins.push({ type: "n", value: o, ins: [] })), t);
|
|
},
|
|
{
|
|
ugen: "Scope",
|
|
description: "renders an an oscilloscope of the current point in the graph. expects values between -1 and 1. warning: this feature is still experimental! when using it, make sure to not switch tabs, as it might fry your browser.",
|
|
compile: ({ vars: [e, a, n, t], ...s }) => w(s, e, a, n, t)
|
|
}
|
|
);
|
|
const P = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
__proto__: null,
|
|
B: En,
|
|
PI: te,
|
|
_: On,
|
|
abs: en,
|
|
acos: Ea,
|
|
ad: Za,
|
|
add: K,
|
|
adsr: Xa,
|
|
and: hn,
|
|
ar: fa,
|
|
argmax: pn,
|
|
argmin: cn,
|
|
asin: Oa,
|
|
atan: Da,
|
|
audioin: ja,
|
|
bipolar: Sn,
|
|
bool: yn,
|
|
bpf: Nn,
|
|
brown: za,
|
|
bytebeat: Ga,
|
|
cc: v,
|
|
ceil: sn,
|
|
clamp: nn,
|
|
clip: Kn,
|
|
clock: ba,
|
|
clockdiv: xa,
|
|
cos: _,
|
|
delay: Ia,
|
|
distort: Ra,
|
|
div: $a,
|
|
dust: Va,
|
|
exp: $,
|
|
feedback: Bn,
|
|
filter: A,
|
|
floatbeat: ya,
|
|
floor: tn,
|
|
fold: Ka,
|
|
fork: zn,
|
|
greater: ee,
|
|
gt: un,
|
|
hold: Ua,
|
|
hpf: Wn,
|
|
ifelse: Xn,
|
|
impulse: D,
|
|
lag: wa,
|
|
lfnoise: Hn,
|
|
log: H,
|
|
lower: ae,
|
|
lpf: Yn,
|
|
lt: mn,
|
|
max: dn,
|
|
midicc: Ja,
|
|
midifreq: ka,
|
|
midigate: Pa,
|
|
midinote: Rn,
|
|
midivel: Fa,
|
|
min: on,
|
|
mix: Qn,
|
|
mod: _a,
|
|
mouseX: An,
|
|
mouseY: qn,
|
|
mul: Aa,
|
|
noise: O,
|
|
not: Gn,
|
|
or: gn,
|
|
output: Mn,
|
|
pan: wn,
|
|
perc: Vn,
|
|
pick: vn,
|
|
pink: Ma,
|
|
poly: ne,
|
|
pow: Qa,
|
|
pulse: Sa,
|
|
qapf: Jn,
|
|
qbpf: Pn,
|
|
qf: In,
|
|
qhpf: kn,
|
|
qlpf: Un,
|
|
qnf: Fn,
|
|
range: fn,
|
|
rangex: xn,
|
|
raw: ga,
|
|
registerUgen: E,
|
|
remap: Zn,
|
|
rng: La,
|
|
round: an,
|
|
saw: Wa,
|
|
scope: _n,
|
|
seq: Ca,
|
|
sign: ln,
|
|
sin: q,
|
|
sine: Na,
|
|
slew: va,
|
|
slide: Ta,
|
|
split: jn,
|
|
src: Ln,
|
|
sub: qa,
|
|
tan: Ba,
|
|
thru: bn,
|
|
time: ha,
|
|
tri: Ha,
|
|
trig: Cn,
|
|
unipolar: Tn,
|
|
xor: rn,
|
|
zaw: Ya
|
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
class et {
|
|
constructor({
|
|
onToggle: a,
|
|
onToggleRecording: n,
|
|
beforeEval: t,
|
|
transpiler: s,
|
|
localScope: o = !1,
|
|
outputNode: d = null
|
|
} = {}) {
|
|
this.outputNode = d, this.audio = new Fe(this.outputNode), this.onToggle = a, this.transpiler = s, this.onToggleRecording = n, this.beforeEval = t, this.localScope = o, typeof window < "u" && (o || (Object.assign(globalThis, k), Object.assign(globalThis, P), Object.assign(globalThis, U), Object.assign(globalThis, { repl: this })), window.addEventListener("message", (p) => {
|
|
p.data.type === "KABELSALAT_SET_CONTROL" && this.audio.setControl(p.data.id, p.data.value);
|
|
}));
|
|
const G = this;
|
|
c.prototype.spawn = function(p = [0, 1], h) {
|
|
G.audio.spawn(this.output(p).exit(), h);
|
|
};
|
|
}
|
|
registerUgen(a, n) {
|
|
return this.audio.registerUgen(n), E(a, n.name);
|
|
}
|
|
evaluate(a) {
|
|
this.localScope || (Object.assign(globalThis, { audio: this.audio }), Object.assign(globalThis, {
|
|
addUgen: this.registerUgen.bind(this)
|
|
}));
|
|
let n;
|
|
this.transpiler ? n = this.transpiler(a) : n = { output: a }, this.beforeEval?.(n);
|
|
let t;
|
|
return this.localScope && (t = {
|
|
...k,
|
|
...P,
|
|
...U,
|
|
audio: this.audio,
|
|
addUgen: this.registerUgen.bind(this),
|
|
repl: this
|
|
}), j(n.output, t);
|
|
}
|
|
async play(a) {
|
|
await this.audio.init(), a.ins.length && this.audio.spawn(a), this.onToggle?.(!0);
|
|
}
|
|
run(a) {
|
|
const n = this.evaluate(a);
|
|
this.play(n);
|
|
}
|
|
stop() {
|
|
this.stopRecording(), this.audio.stop(), this.onToggle?.(!1);
|
|
}
|
|
record() {
|
|
this.audio.record(), this.onToggleRecording?.(!0);
|
|
}
|
|
stopRecording() {
|
|
this.audio.stopRecording(), this.onToggleRecording?.(!1);
|
|
}
|
|
}
|
|
export {
|
|
Fe as AudioView,
|
|
En as B,
|
|
c as Node,
|
|
te as PI,
|
|
et as SalatRepl,
|
|
On as _,
|
|
en as abs,
|
|
Ea as acos,
|
|
Za as ad,
|
|
K as add,
|
|
Xa as adsr,
|
|
hn as and,
|
|
fa as ar,
|
|
pn as argmax,
|
|
cn as argmin,
|
|
Oa as asin,
|
|
Da as atan,
|
|
ja as audioin,
|
|
Sn as bipolar,
|
|
yn as bool,
|
|
Nn as bpf,
|
|
za as brown,
|
|
Ga as bytebeat,
|
|
v as cc,
|
|
sn as ceil,
|
|
nn as clamp,
|
|
Kn as clip,
|
|
ba as clock,
|
|
xa as clockdiv,
|
|
T as compile,
|
|
_ as cos,
|
|
Ia as delay,
|
|
Ra as distort,
|
|
$a as div,
|
|
Va as dust,
|
|
j as evaluate,
|
|
J as exit,
|
|
$ as exp,
|
|
ce as exportModule,
|
|
Bn as feedback,
|
|
A as filter,
|
|
ya as floatbeat,
|
|
tn as floor,
|
|
Ka as fold,
|
|
zn as fork,
|
|
oe as getInletName,
|
|
F as getNode,
|
|
ee as greater,
|
|
un as gt,
|
|
Ua as hold,
|
|
Wn as hpf,
|
|
Xn as ifelse,
|
|
D as impulse,
|
|
wa as lag,
|
|
Hn as lfnoise,
|
|
H as log,
|
|
ae as lower,
|
|
Yn as lpf,
|
|
mn as lt,
|
|
dn as max,
|
|
Ja as midicc,
|
|
ka as midifreq,
|
|
Pa as midigate,
|
|
Rn as midinote,
|
|
Fa as midivel,
|
|
on as min,
|
|
Qn as mix,
|
|
_a as mod,
|
|
y as module,
|
|
An as mouseX,
|
|
qn as mouseY,
|
|
Aa as mul,
|
|
X as n,
|
|
x as node,
|
|
g as nodeRegistry,
|
|
O as noise,
|
|
Gn as not,
|
|
gn as or,
|
|
Mn as output,
|
|
Y as outputType,
|
|
wn as pan,
|
|
Vn as perc,
|
|
vn as pick,
|
|
Ma as pink,
|
|
ne as poly,
|
|
Z as polyType,
|
|
Qa as pow,
|
|
Sa as pulse,
|
|
Jn as qapf,
|
|
Pn as qbpf,
|
|
In as qf,
|
|
kn as qhpf,
|
|
Un as qlpf,
|
|
Fn as qnf,
|
|
fn as range,
|
|
xn as rangex,
|
|
ga as raw,
|
|
u as register,
|
|
l as registerNode,
|
|
E as registerUgen,
|
|
Zn as remap,
|
|
La as rng,
|
|
an as round,
|
|
Wa as saw,
|
|
_n as scope,
|
|
Ca as seq,
|
|
ln as sign,
|
|
q as sin,
|
|
Na as sine,
|
|
va as slew,
|
|
Ta as slide,
|
|
jn as split,
|
|
Ln as src,
|
|
qa as sub,
|
|
Ba as tan,
|
|
bn as thru,
|
|
ha as time,
|
|
Ha as tri,
|
|
Cn as trig,
|
|
Tn as unipolar,
|
|
rn as xor,
|
|
Ya as zaw
|
|
};
|