Micro is a minimalistic audio livecoding environment built on the Web Audio API.
- Editor: CodeMirror-based, hot-exec with Ctrl/Cmd+Enter
- Engine: GraphParser → AudioGraphBuilder → AudioEngine (scheduler)
- Language: Audio nodes routing with
->, note patterns and more
# an instrument and some FX
lead = sine{decay=0.2, sustain=0} -> delay{} -> reverb{} -> OUT
# a pattern
@lead [60 40 50 60 65 48 32 44] 1/2
Go to https://pckerneis.github.io/micro/ and start livecoding!
- Serve the folder (modules require HTTP). Example:
npx vite --port 8080 - Open http://localhost:8080 and click Play
- Edit code, press Execute to hear the changes
- Ctrl/Cmd + S (or Ctrl/Cmd + Enter) to execute the code
- Ctrl/Cmd + Space to toggle play
Declare audio nodes and connect them with ->.
Use the OUT keyword to connect nodes to the output.
synth = sine{} -> OUT
Syntax basics (curly braces with named parameters):
- Synthesis:
sine{attack=0.01, decay=0.2, sustain=0.7, release=0.3} - Effects:
lowpass{frequency=800, Q=1.0},delay{time=0.5, feedback=0.3},gain{level=-6dB} - Samples:
sample{url='https://.../sound.mp3', gain=1.0} - Connect:
a -> b -> OUT
Examples:
# declare a sine synthesizer
lead = sine{decay=0.1, sustain=0}
# connect to gain and to output
lead -> gain{level=-6dB} -> OUT
# you can declare whole audio node chains
bass = square{attack=0.01, sustain=0} -> lowpass{frequency=200} -> gain{level=-8dB} -> OUT
# parallel routing: repeat the source name on multiple lines
lead -> delay{time=0.75} -> gain{level=-12dB} -> OUT
lead -> gain{level=-6dB} -> OUT
You can name a chain and reuse it. When connecting TO a route, it connects to its first node. When connecting FROM a route, it connects from its last node.
chain = lowpass{frequency=800} -> delay{time=0.3}
lead = sine{}
lead -> chain -> OUT
# results in "lead -> lowpass -> delay -> OUT"
You can connect a node's output to another node's AudioParam using index/param syntax:
- Target format:
routeOrName[index].param - Common params:
frequency,detune,gain,Q,playbackRate, ... - If the target is an instrument, the modulation is applied per-note to the underlying source.
- Indexing is zero-based (e.g., in
a -> b -> c,route[0]=a,route[1]=b,route[2]=c).
arp = sine{decay=0.2, sustain=0}
fm = sine{frequency=800, level=120}
fm -> arp.frequency
arp -> OUT
@arp [70 72 74 76] 1/2
Patterns schedule notes or gates: @target [tokens...] stepDuration.
Tokens:
- Rest
"_": no event this step - Continuation
"-": tie/sustain the previous playable step (wrap-around enabled) - MIDI integer: e.g.,
60(converted to Hz internally) - Frequency literal: e.g.,
440Hz,432.5Hz(used as exact frequency)
Duration per token is stepDuration. Continuations add steps to the previous note.
Examples:
@lead [12 - - _ 440Hz -] 1/8
# 12 holds 3 steps, rest 1 step, 440Hz holds 2 steps (ties wrap across loop).
@bass [36 _ 36 _ 36 _ 34 _] 1/4
arp = sine{decay=0.2, sustain=0}
fm = sine{frequency=800, level=120}
fm -> arp.frequency
arp -> OUT
@arp [70 72 74 76] 1/2
amp = gain{level=0.5}
lfo = sine{frequency=4, level=0.5}
lfo -> amp.gain
saw = sawtooth{}
saw -> amp -> gain{level=-12dB} -> OUT
@saw [52 55 59 62] 1/2
kick = sample{url='https://cdn.freesound.org/previews/584/584792_11532701-lq.mp3'} -> OUT
snare = sample{url='https://cdn.freesound.org/previews/13/13751_32468-lq.mp3'} -> reverb{mix=0.2} -> OUT
bass = square{sustain=0, decay=0.1} -> lowpass{frequency=180} -> gain{level=-6dB} -> OUT
@kick [60 _ _ _ _ 60 _ _] 1/2
@snare [_ 60] 1
@snare [_ _ _ _ _ _ _ 60?0.2] 1/4
@bass [36 36 36 34] 1/4
chain = sawtooth{} -> lowpass{frequency=1250, Q=10} -> gain{level=-6dB}
lfo = sine{frequency=0.5, level=1200}
lfo -> chain[1].frequency
chain -> reverb{mix=0.4, length=3} -> OUT
@chain [32] 2
# Samples used:
# - https://freesound.org/people/smedloidian/sounds/787348/
# - https://freesound.org/people/GioMilko/sounds/347089/
# - https://freesound.org/people/DigitalUnderglow/sounds/695697/
amp = gain{level=0.3}
lfo = sine{frequency=8, level=0.2}
lfo -> amp.gain
autofilter = lowpass{q=18, frequency=800}
saw = sawtooth{sustain=0, decay=1} -> delay {mix=0.3, length=0.25, feedback=0.75}
saw -> amp -> autofilter -> reverb{mix=0.6} -> gain{level=-8dB} -> OUT
sine{frequency=0.04, level=390} -> autofilter[0].frequency
bass = sine{} -> gain{level=-12dB} -> reverb{} -> OUT
kick = sample{url='https://cdn.freesound.org/previews/652/652006_11532701-lq.mp3'} -> delay{} -> reverb{} -> OUT
clap = sample{url='https://cdn.freesound.org/previews/695/695697_14904072-lq.mp3'} -> reverb{size=2.5, mix=0.65} -> gain{level=-6dB} -> OUT
seagulls = sample{url='https://cdn.freesound.org/previews/787/787348_5629280-lq.mp3'} -> delay{feedback=0.9} -> reverb{mix=0.8} -> gain{level=3dB} -> OUT
@saw [52 55 59 62] 1/2
@bass [40 36]16
@kick [64]4
@clap [_ _ _ 56?0.5]2
@seagulls [52?0.6 54?0.6 54?0.6]8