eseq is an extensible, customizable DAW that grows with you.
Free · macOS & Linux
eseq is built in a dialect of LISP that lets you break open and extend just about anything:
from custom sequencers , to new layouts, to even new instruments .
A Rust core and C audio engine keeps thing fast, so you never skip a beat.
Open source because your tools should be free/libre.
eseq is centered around a hardware-style step sequencer, letting you write patterns quickly when inspiration strikes.

A step grid for every track. Tap in a beat, hear it on the next bar, and keep the mixer and effects one glance away.

Lock any parameter to any step. One hit can be brighter, shorter, or slower than the rest. Locks reach into instruments, effects, and the sequencer itself.

Generative lanes. Add lanes under any track that roll dice, count, and compare, and wire them into any setting. Patterns change on their own over time.
Why limit yourself to what exists? Every instrument in eseq is written in dgenlisp, a sample-by-sample DSP language in the spirit of Gen, with tensors and macros on top, and agents love to write it.

Patch it by hand. Open any instrument as a patch of connected modules, rewire it, and save your own version.
;; One operator: a cosine whose phase runs through a triangle shaper.
(defmacro fm-op (freq shape)
(def ph (phasor freq))
(def tri (triangle ph shape))
(cos (* tri twopi)))
;; Two operators, the second detuned, under a percussive stab envelope.
(defmacro fm-stab (freq gate_sig trig_sig shape detune_st decay_ms vel level)
(def stab_env (adsr gate_sig trig_sig 19 decay_ms 0.01 300))
(def op_a (fm-op freq shape))
(def op_b (fm-op (pitch-transpose freq detune_st) shape))
(def pair (mix op_a op_b 0.4))
(* pair stab_env vel level))
(param fm_rate @default 1.06 @min 0.1 @max 8 @unit Hz @mod true)
(param unison @default 0.27 @min 0 @max 1 @unit st @mod true)
(def shape (phasor (mod fm_rate)))
(def stab (fm-stab pitch gate trigger shape (mod unison)
stab_decay_ms velocity (mod gain)))Or write it. Revsynt, a built-in FM synth, starts from two small macros: an operator, then a stab built from two of them.
;; A 2-pole modal resonator: y = 2r·cos(w)·y1 - r²·y2 + x.
;; Every line runs once per sample, so feedback is just history.
(defmacro rimmode (x f t60s y1h y2h)
(def w0 (* twopi (/ (clip f 40 18000) samplerate)))
(def rr (exp (/ -6.9077553 (* samplerate (max t60s 0.001)))))
(def y1v (read-history y1h))
(def y2v (read-history y2h))
(def y (+ (* 2 rr (cos w0) y1v) (* -1 rr rr y2v) x))
(write-history y2h y1v)
(write-history y1h y)
y)
;; A metal hoop's modes sit near 1 : 2.76 : 5.40.
(def rim-m1 (rimmode rim-in rim-pitch-v rim-t60 rm1y1 rm1y2))
(def rim-m2 (rimmode rim-in (* rim-pitch-v 2.76) (* rim-t60 0.6) rm2y1 rm2y2))
(def rim-m3 (rimmode rim-in (* rim-pitch-v 5.40) (* rim-t60 0.35) rm3y1 rm3y2))Sample by sample. Like Gen in Max, every line runs once per sample, so any feedback is a few lines: FM feedback, biquads, waveguides. The Membrane Snare’s rim rings on three of these.
;; The Laplacian: how each point on a membrane pulls on its neighbours.
(def laplacian (tensor @shape [3 3] @data [0 1 0
1 -4 1
0 1 0]))
;; Every sample, the 6x6 drumhead is convolved with it.
;; tension + viscosity + bending in ONE outer convolution:
(def p-l1 (conv2d p-state laplacian @padding same))
(def p-field (+ (* p-state p-stiff)
(* (- p-state p-prev) tone-damp-v)
(* p-l1 (* -1 p-stretch-k))))
(def p-lap (conv2d p-field laplacian @padding same))
;; ...and the head's next position falls out of it.
(def p-next (+ (- (* (- 2 p-damp-t) p-state) (* (- 1 p-damp-t) p-prev))
p-lap
(* strike-force strike-mask-m)))Tensors in the loop. The same snare’s heads are 6×6 grids, convolved with a Laplacian every sample to make a physical drumhead. All of it is JIT-compiled to SIMD-optimized C.
Build your own live-coding surfaces in LISP, with a UI that plays like part of a groovebox. Every scene remembers its own patterns and settings.
;; How many notes step i plays: hits spread evenly.
(def step-hits (steps hits rot i)
(let ((j (wrap (- i rot) steps)))
(- (floor (/ (* j hits) steps))
(floor (/ (* (- j 1) hits) steps)))))
;; Each ring counts the transport modulo its own
;; length, playing its next note when a hit lands.
(def ring-tick (ring i tk)
(let ((n (get ring :steps)))
(let ((cycle (floor (/ tk n))) (step (mod tk n)))
(let ((r (step-hits n (cycle-hits ring cycle)
(get ring :rot) step)))
(if (> r 0)
(let ((count (hit-count i)))
(let ((note (row-at (get ring :note) count))
(vel (row-at (get ring :vel) count)))
(do
(state-set! (str "eu-hits-" i) (+ count 1))
(map (lambda (k)
(seq-emit :track (get ring :track)
:at (* k (/ step-beats r))
:vel (nth vel 0)
:note (nth note 0)))
(range 0 r)))))
nil)))))
Euclidean rings. Rings of different lengths drift apart and meet again, so a few numbers make polyrhythms that keep turning over.
(jak "jaki 1" :16
((fig (- -) (rep 4)) (fig (. - .))
-> 0 (on (fig 1) left) (minvel 0)
(dashdecay 0.48) (dotdecay 0.03) left
-> 2 (minvel 0.04) (dashdecay 0.47)
(note (seq :hit 4 19 (0 12 14 0) 2 0 2 0 12))
(shift 2))
((fig (. . -))
-> 1 (minvel 0.23) (dashdecay (0 0.4 0.15 0.02))
(every 8 half) (dotdecay 0)
-> 3 right (quant :4)))
A language of your own. This one follows Jaki Liebezeit’s way of building grooves from a few short figures. Yours could be anything.
(def-node nrn
:reduce :sum
:state ((energy :leak (per-step :energy-decay)))
;; Fire when energy clears threshold. The else-branch returns nil (no fire).
:update (if (>= (energy) (param :threshold))
(do
(dampen-incoming (param :dampening))
(emit :note (+ (param :global-transpose)
(if (>= (param :transpose-reset) 1)
(param :transpose)
(+ (in-note) (param :transpose))))
:dur (* (delay) (param :dur-factor))
:vel (if (>= (param :vel-reset) 1)
1
(* (in-vel) (param :vel-decay)))))
(recover-incoming (param :recovery))))
(edges
:from nrn
:to nrn
:topology (all-to-all)
:gather (- (edge :weight) (edge :dampening)))
Neural graph. Nodes fire each other, so a pattern keeps finding new paths through the network.
Every sequencer here is a package, just a folder of LISP files. Attach one to a project, load it everywhere, or open its source and change it, all from the browser.
