Skip to content

Instantly share code, notes, and snippets.

@amiika
Last active February 10, 2026 23:30
Show Gist options
  • Select an option

  • Save amiika/ebf911fe7ee85eb8f13bfc1de6dbcb81 to your computer and use it in GitHub Desktop.

Select an option

Save amiika/ebf911fe7ee85eb8f13bfc1de6dbcb81 to your computer and use it in GitHub Desktop.
Funcbeat pattern function library
// monkeypatchers pattern library inspired by tidalcycles
const r = t => 0; // Rest
const pitch = (n) => 55 * pow(2, n / 12);
const repeat = (val, n) => Array(n).fill(val);
const speed = (s, pat) => t => {
const rate = typeof s === 'function' ? s(t) : s;
return pat(t * rate);
};
const seq = (...args) => t => {
const pats = args.flat();
const n = pats.length;
const i = floor(t * n);
return (pats[i % n] || r)(floor(t) + (t * n % 1));
}
const cat = (...args) => t => {
const list = args.flat();
const len = list.length;
const i = floor(t);
const val = list[i % len];
return (typeof val === 'function') ? val(floor(t / len) + (t % 1)) : val;
}
const stack = (...args) => t => {
const pats = args.flat();
let sum = 0;
for(let i=0; i<pats.length; i++) sum += pats[i](t);
return sum;
}
const list = (...vals) => t => {
const n = vals.length;
const i = floor(t * n);
return vals[i % n];
}
const chord = (inst, ...vals) => stack(...vals.map(n => inst(n)));
const gain = (vol, pat) => t => pat(t) * vol;
const clip = (x, n) => x > n ? n : x < -n ? -n : x;
const clamp = (x, a, b) => min(b, max(a, x));
// DSP
const saw = (f, t) => 1 - 2 * (t % (1 / f)) * f;
const sqr = (f, t) => sin(t * f * PI * 2) > 0 ? 1 : -1;
const tri = (f, t) => abs(1 - (2 * t * f) % 2) * 2 - 1;
const noise = () => random() * 2 - 1;
const acid = (pattern) => {
let phase = 0;
let note = 0;
let cut = 0;
return t => {
const target = pattern(t);
const gate = (target !== null && target !== undefined) ? 1 : 0;
if (gate) note += (target - note) * 0.0015;
const f = pitch(note);
phase += f / 44100;
if (phase >= 1) phase -= 1;
const wave = 2 * (phase - 0.5);
const subT = (t * 16) % 1;
const env = exp(-6 * subT);
const cutoff = 0.02 + (0.45 * env);
cut += (wave - cut) * cutoff;
return tanh(cut * 5) * 0.7 * gate;
}
}
const pad = (n) => t => {
const f = pitch(n) * 150;
return (
sin(t * f) * 0.5 +
sin(t * f * 2.01) * 0.25 +
sin(t * f * 1.5) * 0.1
)
}
// DRUMS
const perc = (wave, decay, o) => {
const env = max(0, 0.889 - (o * decay) / ((o * decay) + 1));
return wave * env * env;
}
const bd = t => {
const localT = t % 1;
const wave = tanh(sin(cbrt(localT) * 160) * 8);
return wave * exp(-4 * localT);
}
const hh = t => noise() * exp(-60 * (t % 1))
const sn = t => {
const lt = t % 1;
const raw = tri(200, lt) + noise();
return clip(raw * 5, 0.5) * exp(-15 * lt);
}
const cowbell = t => {
const lt = t % 1;
const wave = sqr(666, lt) + sqr(999,lt);
return perc(wave, 7, t%2) * 0.5;
}
const oh = t => {
const localT = t % 1;
const n = noise() + ((t * 32768) & 1 ? -0.25 : 0.25);
return n * exp(-20 * localT);
}
// Composition
const line1 = list(0, 0, 12, 0, 0, 0, 10, 0);
const line2 = list(0, 0, 12, 12, 15, 12, 10, 0);
const line3 = list(12, 12, 0, 12, 0, 10, 0, 10);
const synth303 = acid(
cat(
repeat(line1, 3),
line2,
repeat(line3, 2)
)
)
const cm7 = chord(pad, 0, 3, 7, 10);
const fm7 = chord(pad, 5, 8, 12, 15);
const bb7 = chord(pad, 10, 14, 17, 20);
const ebM = chord(pad, 3, 7, 10, 14);
const abM = chord(pad, 8, 12, 15, 19);
const g7 = chord(pad, 7, 11, 14, 17);
const chords = cat(
cm7,
fm7,
seq(bb7, ebM),
seq(abM, g7)
)
const padGate = list(0.25,0.5,0.5,0.25,0.25);
const kicks = seq(bd,bd,bd,bd);
const hits = stack(
seq(r, hh, r, r),
seq(r, cat(r,sn), sn, r),
cat(
repeat(seq(r, r, oh, cowbell), 3),
seq(cowbell, cowbell, cowbell, cowbell)
),
t => seq(hh, r, hh, r)(t * cat(2, 4, 8)(t))
);
const BPM = 135;
return t => {
const m = t * (BPM / 60) / 4;
const acidFade = clamp((t - 1) / 4, 0, 1);
const hitsGate = (t > 6) ? 1 : 0;
const kickGate = (t > 8) ? 1 : 0;
const drill = cat(repeat(1,32),2,2,4,4,8,8,12,14,repeat(0,6))(t);
return stack(
t => kicks(t * drill) * kickGate,
t => hits(t) * hitsGate,
t => synth303(t) * acidFade * 0.5,
t => chords(t) * padGate(t * cat(6,8)(t)) * 0.15
)(m)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment