License
This project is licensed under AGPL-3.0 and is inspired by strudel (https://strudel.cc/) and hydra (https://hydra.ojack.xyz/).
It integrates strudel's uzu patterns for sequencing and it also integrates superdough (strudel's webaudio engine) as a sampler.
Reference
Generator
Functions that generate a new signal
ad
ad(trigger, attack, decay, curve='e') => Signal
trigger [Signal|Pattern|Number]
attack [Number]
decay [Number]
curve [String] = 'e'
d1: sine(sig(30).add(ad("[1*8?0.75]*2",0,0.25).mul(200))).coarse(8).out()
adr
adr(trigger, attack, decay, release=0, curve='e') => Signal
trigger [Signal|Pattern|Number]
attack [Number]
decay [Number]
release [Number] = 0
curve [String] = 'e'
d1: tri(100).mul(adr("[t ~ ~ t ~ ~ t ~]",0,1,0,'l')).out()
adsr
adsr(trigger, attack, decay, sustain=0, release=0, curve='e') => Signal
trigger [Signal|Pattern|Number]
attack [Number]
decay [Number]
sustain [Number] = 0
release [Number] = 0
curve [String] = 'e'
d1: tri(100).mul(adsr("[t ~ ~ ~ t ~ ~ ~]*0.75",0.125,1,0.25,0.125,'e')).out()
and
and(args) => Signal
args [Signal]
d1: and(saw(99),supersaw(50)).out()
brown
brown() => Signal
d1: brown().out()
bytebeat
bytebeat(frequency, expression) => Signal
frequency [Signal|Pattern|Number]
expression [string|number]
d1: bytebeat(40,'(t*(t*8%60 <= 300)|(-t)*(t*4%512 < 256))+t/400').out()
crackle
crackle(density=0.02) => Signal
density [Number] = 0.02
d1: crackle(0.05).out()
d
d(pattern) => Signal
pattern [Pattern]
d1: d(s("bd").fast(8)).out()
env
env(trigger, points="1-0:0-1", defaultType='e') => Signal
trigger [Signal|Pattern|Number]
points [String] = "1-0:0-1"
defaultType [String] = 'e'
d1: saw(50).mul(env(sine(1),'1-0:0-1')).out()
d1: sine(200).mul(env("1 ~ ~ 1 ~ ~ 1 ~",'1-0:0-1')).out()
gran
gran(s, options={rate=1, pos=0, rpos=0, size=0.125, dens=8}) => Signal
s [Signal|Pattern|Number]
options [Object] = {
rate [Signal|Pattern|Number] = 1
pos [Signal|Pattern|Number] = 0
rpos [Signal|Pattern|Number] = 0
size [Signal|Pattern|Number] = 0.125
dens [Signal|Pattern|Number] = 8 }
d1: gran("nvox:3", {rate: -1, pos: 0.5, rpos: 0, size: 0.25, dens: 8}).send((x) => x.datorro(1)).out();
input
input(index=0) => Signal
index [Number] = 0
d1: saw(50).nlpf(0.25).out(1); d2: input(1).out();
d1: plaits(43, {harm: 0.4, morph: uperlin(0.1)}) .out(1) .nbpf(uperlin(0.01),0.125) .mul(2) .mul(input(1).nbpf(uperlin(0.1,835),0.125).mul(2)) .send(x=>x.datorro(1)) .out()
lad
lad(trigger, attack, decay) => Signal
trigger [Signal|Pattern|Number]
attack [Number]
decay [Number]
sine(200).mul(lad("[t ~ ~ t ~ ~ t ~]*2",0,1)).out()
ladr
ladr(trigger, attack, decay, release=0) => Signal
trigger [Signal|Pattern|Number]
attack [Number]
decay [Number]
release [Number] = 0
d1: saw(50).mul(ladr("[t ~ ~ t ~ ~ t ~]",0,1,0.25)).lpf(0.25).out()
ladsr
ladsr(trigger, attack, decay, sustain=0, release=0) => Signal
trigger [Signal|Pattern|Number]
attack [Number]
decay [Number]
sustain [Number] = 0
release [Number] = 0
d1: tri(100).mul(ladsr("[t ~ ~ ~ t ~ ~ ~]*0.75",0,1,0.25,0.125)).out()
lenv
lenv(trigger, points='1-0:0-1') => Signal
trigger [Signal|Pattern|Number]
points [String] = '1-0:0-1'
d1: sine(200).mul(lenv("1 ~ ~ 1 ~ ~ 1 ~",'1-0:0-1')).out()
max
max(args) => Signal
args [Signal]
d1: max(saw(99),supersaw(50)).out()
min
min(args) => Signal
args [Signal]
d1: min(saw(99),supersaw(50)).out()
mix
mix(args) => Signal
args [Signal]
d1: mix(saw(50),saw(100),saw(200)).lpf(0.25).out()
mtof
mtof(note, transpose=0) => Signal
note [Signal|Pattern|Number]
transpose [Number] = 0
d1: sine(mtof("[0 3 5 7 12]*[2|3|4|5]",48)).out()
nosc
nosc(frequency, options={wave=0, sync=0, samt=1, sratio=1, pw=0.5}) => Signal
frequency [Signal|Pattern|Number]
options [Object] = {
wave [Signal|Pattern|Number] = 0
sync [Signal|Pattern|Number] = 0
samt [Signal|Pattern|Number] = 1
sratio [Signal|Pattern|Number] = 1
pw [Signal|Pattern|Number] = 0.5 }
d1: nosc(50, {wave: 3, pw: uperlin(0.125)}).lpf(0.4).out()
d1: nosc(sig(30).add(perlin(1).mul(10)), { wave: 2, sync: sine(40), samt: uperlin(1) }).bpf(uperlin(0.1),.125).mul(2) .send(x=>x.datorro(0.5)) .out()
or
or(args) => Signal
args [Signal]
d1: or(saw(99),supersaw(50)).out()
perlin
perlin(frequency, offset) => Signal
frequency [Signal|Pattern|Number]
offset [Signal|Pattern|Number]
d1: plaits(40, {harm: 0.4, morph: perlin(1).map(-1,1,0,1)}).out()
pink
pink() => Signal
d1: pink().mul("[0 0 0 0 1 0 0 0]*2").add(pink().mul("[[1 0 0 0]*16]").mul(0.5)).out()
pulse
pulse(frequency, pulsewidth=0) => Signal
frequency [Signal|Pattern|Number]
pulsewidth [Signal|Pattern|Number] = 0
d1: pulse(50,sine(0.01)).lpf(0.5).out()
saw
saw(frequency) => Signal
frequency [Signal|Pattern|Number]
d1: saw(50).mul(saw(49.9)).lpf(0.5).out()
sig
sig(value) => Signal
value [Signal|Pattern|Number]
d1: saw(sig(50).mul(2)).lpf(0.25).out()
sine
sine(frequency) => Signal
frequency [Signal|Pattern|Number]
d1: sine(200).mul(saw(sig(50).add(1))).out()
slide
slide(pattern, curve) => Signal
pattern [Pattern]
curve [Signal|Pattern|Number]
d1: saw(50).nlpf(slide("[0 0.5 0 0.5]")).out()
square
square(frequency) => Signal
frequency [Signal|Pattern|Number]
d1: square(mtof("[0 7 12 19 24]*4",36)).lpf(sine(0.1).mul(0.25).add(0.5)).out()
supersaw
supersaw(frequency, detune=0.125, voices=5) => Signal
frequency [Signal|Pattern|Number]
detune [Signal|Pattern|Number] = 0.125
voices [Signal|Pattern|Number] = 5
d1: supersaw(50,sig(0.125).add(sine(0.1).mul(0.125)),5).out()
tri
tri(frequency) => Signal
frequency [Signal|Pattern|Number]
d1: tri(100).mul(tri(sig(50).add(1))).out()
uperlin
uperlin(frequency, offset) => Signal
frequency [Signal|Pattern|Number]
offset [Signal|Pattern|Number]
d1: plaits(40, {harm: 0.4, morph: uperlin(1)}).out()
usaw
usaw(frequency) => Signal
frequency [Signal|Pattern|Number]
d1: saw(50).lpf(usaw(1)).out()
usine
usine(frequency) => Signal
frequency [Signal|Pattern|Number]
d1: saw(50).lpf(usaw(usine(0.1)).mul(0.5)).out()
usquare
usquare(frequency) => Signal
frequency [Signal|Pattern|Number]
d1: saw(50).lpf(usquare(1)).out()
utri
utri(frequency) => Signal
frequency [Signal|Pattern|Number]
d1: saw(50).lpf(utri(1)).out()
white
white() => Signal
d1: white().mul("[0 0 0 0 1 0 0 0]*2").add(white().mul("[[1 0 0 0]*16]").mul(0.5)).out()
wt
wt(frequency, options={s='bd:0', pos=0, detune=0.125, voices=3, spread=0.5, mode=0, warp=0}) => Signal
frequency [Signal|Pattern|Number]
options [Object] = {
s [String] = 'bd:0'
pos [Signal|Pattern|Number] = 0
detune [Signal|Pattern|Number] = 0.125
voices [Signal|Pattern|Number] = 3
spread [Signal|Pattern|Number] = 0.5
mode [Signal|Pattern|Number] = 0
warp [Signal|Pattern|Number] = 0 }
d1: wt(40,{s: 'bd:0', pos: sine(0.01), detune: 0.125, voices: 3}).out()
d1: wt(20, {s: "nwt:0", pos: uperlin(0.1)}).out(1) .nbpf(uperlin(0.01),0.125).mul(2) .mul(input(1).nbpf(uperlin(0.1,835),0.125).mul(2)) .send(x=>x.datorro(1, {decay: 0.5, rate: 0.5, depth: 1})) .send(y=>y.delay(0.33,0.25)).out()
xand
xand(args) => Signal
args [Signal]
d1: xand(saw(99),supersaw(50)).out()
xor
xor(args) => Signal
args [Signal]
d1: xor(saw(99),supersaw(50)).out()
Processor
Functions that are chainable to a signal
abs
abs() => Signal
d1: sine(200).abs().out()
add
add(value) => Signal
value [Signal|Pattern|Number]
d1: sine(mtof(48)).add(sine(mtof(55))).out()
d1: sine(mtof(sig(48).add("[0 3 5 7 12]*4"))).out()
asym
asym(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).asym(2,1).out()
atan
atan() => Signal
d1: sine(200).atan().out()
bip
bip() => Signal
d1: saw(50).djf(usine(0.5).bip()).out()
bpf
bpf(frequency, resonance=1, amount=1) => Signal
frequency [Signal|Pattern|Number]
resonance [Signal|Pattern|Number] = 1
amount [Number] = 1
d1: supersaw(mtof(36)).bpf(mtof([48,48+7]).add(sine(mtof(36+7)).mul(300)),1).out()
chebyshev
chebyshev(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).chebyshev(2,1).out()
clamp
clamp(min, max) => Signal
min [Signal|Pattern|Number]
max [Signal|Pattern|Number]
d1: sine(200).clamp(-0.5,0.5).out(1)
coarse
coarse(factor) => Signal
factor [Signal|Pattern|Number]
d1: sine(100).coarse(irand(32,1).fast(16)).out()
compressor
compressor(pregain=1, threshold=-9, ratio=6, knee=3, attack=0.001, release=0.01) => Signal
pregain [Signal|Pattern|Number] = 1
threshold [Signal|Pattern|Number] = -9
ratio [Signal|Pattern|Number] = 6
knee [Signal|Pattern|Number] = 3
attack [Signal|Pattern|Number] = 0.001
release [Signal|Pattern|Number] = 0.01
d1: saw(200).compressor().out()
cos
cos() => Signal
d1: sine(200).cos().out()
crush
crush(depth) => Signal
depth [Signal|Pattern|Number]
d1: sine(50).crush(irand(16,1).fast(16)).out()
cubic
cubic(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).cubic(2,1).out()
datorro
datorro(volume, options={decay=0.5, damp=0.5, indiff=0.5, decdiff=0.5, band=1, predel=0, rate=0.5, depth=1}) => Signal
volume [Signal|Pattern|Number]
options [Object] = {
decay [Signal|Pattern|Number] = 0.5
damp [Signal|Pattern|Number] = 0.5
indiff [Signal|Pattern|Number] = 0.5
decdiff [Signal|Pattern|Number] = 0.5
band [Signal|Pattern|Number] = 1
predel [Signal|Pattern|Number] = 0
rate [Signal|Pattern|Number] = 0.5
depth [Signal|Pattern|Number] = 1 }
d1: plaits(43, {harm: 0.4, morph: uperlin(0.1)}).send(x=>x.datorro(1, {decay: 0.5, rate: 0.5, depth: 1})).out()
delay
delay(time=0.33, feedback=0.5) => Signal
time [Signal|Pattern|Number] = 0.33
feedback [Signal|Pattern|Number] = 0.5
d1: saw(30).djf(saw(0.5).map(-1,1,0,0.3)).send(x=>x.delay(0.3,0.6).mul(0.7)).out()
diode
diode(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).diode(2,1).out()
distort
distort(amount, postgain=1, algorithm='scurve') => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
algorithm [String] = 'scurve'
d1: sine(50).distort(2,1).out()
djf
djf(value, resonance=0.125, amount=1) => Signal
value [Signal|Pattern|Number]
resonance [Signal|Pattern|Number] = 0.125
amount [Number] = 1
d1: supersaw(40,0.125).djf(sine(0.03).map(-1,1,0,1)).out()
eqh
eqh(frequency, gain) => Signal
frequency [Signal|Pattern|Number]
gain [Signal|Pattern|Number]
eql
eql(frequency, gain) => Signal
frequency [Signal|Pattern|Number]
gain [Signal|Pattern|Number]
eqm
eqm(frequency, gain, resonance=1) => Signal
frequency [Signal|Pattern|Number]
gain [Signal|Pattern|Number]
resonance [Signal|Pattern|Number] = 1
exp
exp() => Signal
d1: sine(200).exp().out()
fold
fold(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).fold(2,1).out()
hard
hard(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).hard(2,1).out()
hpf
hpf(frequency, resonance=1, amount=1) => Signal
frequency [Signal|Pattern|Number]
resonance [Signal|Pattern|Number] = 1
amount [Number] = 1
limiter
limiter(threshold=0, attack=0.001, release=0.01) => Signal
threshold [Signal|Pattern|Number] = 0
attack [Signal|Pattern|Number] = 0.001
release [Signal|Pattern|Number] = 0.01
d1: saw(48).limiter().out()
log
log() => Signal
d1: sine(200).log().out()
lpf
lpf(frequency, resonance=1, amount=1) => Signal
frequency [Signal|Pattern|Number]
resonance [Signal|Pattern|Number] = 1
amount [Number] = 1
d1: saw(50).lpf(sine(49*2).mul(100).add(101)).out()
map
map(inMin=-1, inMax=1, outMin=0, outMax=1) => Signal
inMin [Signal|Pattern|Number] = -1
inMax [Signal|Pattern|Number] = 1
outMin [Signal|Pattern|Number] = 0
outMax [Signal|Pattern|Number] = 1
d1: saw(50).djf(sine(0.5).map(-1,1,0.2,0.4)).out()
mapx
mapx(inMin=-1, inMax=1, outMin=0, outMax=1) => Signal
inMin [Signal|Pattern|Number] = -1
inMax [Signal|Pattern|Number] = 1
outMin [Signal|Pattern|Number] = 0
outMax [Signal|Pattern|Number] = 1
d1: saw(50).djf(sine(0.5).mapx(-1,1,0.2,0.4)).out()
mod
mod(value) => Signal
value [Signal|Pattern|Number]
d1: sine(200).mod(1).out(1)
mul
mul(value) => Signal
value [Signal|Pattern|Number]
d1: saw(50).mul(sine(199)).out()
d1: tri(100).mul(2).out()
d1: pulse(50).mul(lad("1 0",0,1)).out()
nbpf
nbpf(value, resonance=0.125, amount=1) => Signal
value [Signal|Pattern|Number]
resonance [Signal|Pattern|Number] = 0.125
amount [Number] = 1
d1: pulse(40,sine(0.01)).nbpf(usine(0.01)).out()
nhpf
nhpf(scaledfreq, resonance=0.125, amount=1) => Signal
scaledfreq [Signal|Pattern|Number]
resonance [Signal|Pattern|Number] = 0.125
amount [Number] = 1
d1: supersaw(50).nhpf(usine(49.9).mul(0.875)).out()
nlpf
nlpf(value, resonance=0.125, amount=1) => Signal
value [Signal|Pattern|Number]
resonance [Signal|Pattern|Number] = 0.125
amount [Number] = 1
d1: supersaw(50).nlpf(usine(49.9).mul(0.875)).out()
out
out(index=0) => Signal
index [Number] = 0
sine(200).out()
d1: sine(200).out(1) d2: input(1).out(0)
range
range(min=0, max=1) => Signal
min [Signal|Pattern|Number] = 0
max [Signal|Pattern|Number] = 1
d1: saw(50).djf(sine(0.5).range(0.2,0.4)).out()
rangex
rangex(min=0, max=1) => Signal
min [Signal|Pattern|Number] = 0
max [Signal|Pattern|Number] = 1
d1: saw(50).djf(sine(0.5).rangex(0.2,0.4)).out()
room
room(duration=5, predelay=0, lowpass=15000, dim=1000) => Signal
duration [Signal|Pattern|Number] = 5
predelay [Signal|Pattern|Number] = 0
lowpass [Signal|Pattern|Number] = 15000
dim [Signal|Pattern|Number] = 1000
sine(mtof("[0|3|5|7|12|15|17|19|24]*16?0.875",48)).mul(0.5).send(x=>x.room(5)).out()
scurve
scurve(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).scurve(2,1).out()
self
self(func) => Signal
func [Signal|Pattern|Number]
d1: sine(50).self(x=>x.mul(sine(x.mul(50).add(1)))).out()
send
send(func, dry=1) => Signal
func [Signal|Pattern|Number]
dry [Signal|Pattern|Number] = 1
d1: supersaw(50,sine(0.1).map(-1,1,1/16,1/8)).send(x=>x.delay(0.25,0.25).room(0.5)).out()
sin
sin() => Signal
d1: sine(200).sin().out()
sinefold
sinefold(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).sinefold(2,1).out()
slew
slew(rate) => Signal
rate [Signal|Pattern|Number]
d1: saw(100).nlpf(sig("1 0 1 0").slew(1/1000)).out()
soft
soft(amount, postgain=1) => Signal
amount [Signal|Pattern|Number]
postgain [Signal|Pattern|Number] = 1
d1: sine(50).soft(2,1).out()
stretch
stretch(factor) => Signal
factor [Signal|Pattern|Number]
d1: saw(50).add(saw(50).stretch(1)).out()
tan
tan() => Signal
d1: sine(200).tan().out()
uni
uni() => Signal
d1: saw(50).djf(sine(0.5).uni()).out()
urange
urange(min=0, max=1) => Signal
min [Signal|Pattern|Number] = 0
max [Signal|Pattern|Number] = 1
d1: saw(50).djf(usine(0.5).urange(0.2,0.4)).out()
urangex
urangex(min=0, max=1) => Signal
min [Signal|Pattern|Number] = 0
max [Signal|Pattern|Number] = 1
d1: saw(50).djf(usine(0.5).urangex(0.2,0.4)).out()
vowel
vowel(vowel) => Signal
vowel [String]
d1: saw(100).vowel('a').mul(4).out()
wcompressor
wcompressor(threshold=-6, ratio=9, knee=3, attack=0.001, release=0.01) => Signal
threshold [Signal|Pattern|Number] = -6
ratio [Signal|Pattern|Number] = 9
knee [Signal|Pattern|Number] = 3
attack [Signal|Pattern|Number] = 0.001
release [Signal|Pattern|Number] = 0.01
d1: saw(50).wcompressor().out()
Sequencer
Functions that generate a sequence
p
p(pattern) => Pattern
pattern [Pattern]
d1: sine(mtof(p(0,3,5,7,12).fast(4),48)).out()
step
step(pattern) => Pattern
pattern [Pattern]
d1: d(step("x..x..x.").s("bd:4")).out()
d1: d(stack( step("x..x..x.").fast(2).s("bd:4"), step("....x...").fast(2).s("sd:4").clip(0.25).gain(0.25), step("..x...x.").fast(2).s("oh:2").clip(0.25).gain(0.25), )).out()