LJam is a browser-based loop sequencer with a 6-track grid interface. It uses Tone.js for built-in synthesis and supports Web MIDI output so you can drive external instruments and DAWs directly from the browser.
Six tracks are arranged in a 3×2 grid: two drum panels and four melodic synth panels. Each track has up to 26 slots and 8 chains for building arrangements on the fly, and plays to one output: the built-in synth, a sample kit, or a MIDI device.
Each grid panel has its own instrument. Drum panels let you toggle individual hits; melodic panels let you draw notes with variable length.
The interface is a fixed 3×2 layout of grid panels. Each panel is 32 steps long (two bars of 16 sixteenth notes).
| Position | Track | Type | Default Rows | Color |
|---|---|---|---|---|
| Top-left | KICK / SNARE | Drum | 6 instruments | Red |
| Top-center | PERCUSSION | Drum | 7 instruments | Orange |
| Top-right | BASS | Melodic | Scale-dependent | Green |
| Bottom-left | LEAD SYNTH | Melodic | Scale-dependent | Blue |
| Bottom-center | PAD / CHORDS | Melodic | Scale-dependent | Purple |
| Bottom-right | ARP / FX | Melodic | Scale-dependent | Cyan |
If bar 2 (steps 17–32) is empty for a track, the playhead loops at step 16 for that track.
Each track has up to 26 independent slots labeled A through Z. Think of them as pattern variations for a single track. Slot tabs appear as you need them: every slot in use is shown, plus one empty tab after the last, so a fresh track shows two tabs and a busy one shows what it uses. A slot that holds notes, sits in a chain or is painted in the arranger is never hidden.
Chains let you sequence slots into longer patterns. Each track has 8 chains.
When a chain is active, the sequencer automatically advances to the next slot in the chain at each loop boundary, wrapping around at the end.
The arranger is a timeline strip under the transport bar for building a song out of your slots and chains. Each row is one track, each column is one bar. Click ▸ ARRANGE to unfold it.
The arrangement is saved with the project. CLR removes every block and is undoable.
| Control | Range | Default |
|---|---|---|
| BPM | 60–200 | 120 |
| Swing | 0–100% | 0% |
| Play / Stop | — | Stopped |
BPM and swing update live without stopping playback. Swing delays every second sixteenth note by the set amount, giving a shuffle feel.
The step indicator at the bottom of the transport bar shows the current playback position.
VU next to it opens a small output meter: the fill is the RMS level, the bar the peak, the white tick the held peak and the dot lights on a clip (ticks at −24, −12, −6 and 0 dBFS). Click it again for an oscilloscope of the output, and once more to hide it. While the meter is on, a thin level line runs under every track’s VOL slider. A full-velocity hit on any track peaks around −12 dBFS with its fader at 0 dB, so six tracks at the default −6 dB stay under 0; faders at +6 will clip the master, which has no limiter.
The master key and master scale in the transport bar control all melodic grids by default.
C C# D D# E
F F# G G# A
A# B
| Scale | Intervals (semitones) |
|---|---|
| Major | 0 2 4 5 7 9 11 |
| Minor | 0 2 3 5 7 8 10 |
| Dorian | 0 2 3 5 7 9 10 |
| Mixolydian | 0 2 4 5 7 9 10 |
| Pent Maj | 0 2 4 7 9 |
| Pent Min | 0 3 5 7 10 |
| Blues | 0 3 5 6 7 10 |
| Chromatic | 0 1 2 3 4 5 6 7 8 9 10 11 |
Each melodic panel has its own root and scale dropdowns in the panel header. Setting these overrides the master key/scale for that grid only — useful for polytonality or mixing scale colors.
On melodic grids, click and drag the row labels (the note names on the left edge) up or down to shift the octave range.
| Track | Default Octaves |
|---|---|
| Bass | 2–3 |
| Lead Synth | 4–5 |
| Pad / Chords | 3–4 |
| Arp / FX | 5–6 |
Click a track’s name label to rename it. The label becomes an editable text field.
Custom labels are saved with your project.
On drum grids, drag a row label (e.g. KICK, SNARE) up or down to trim that row’s level, from −24 to +6 dB. The thin bar under the label shows where it sits, and the label reads the value while you drag. Alt-click resets it to 0 dB. The trim applies the same way whatever the track’s OUT is: it scales the built-in synth, the sampler, and MIDI velocity. Per-hit accents are still the note velocities; this is the static mix of the row. A sample that is simply recorded too hot is better trimmed once in Waverly, where the gain travels with the kit.
Double-click a row label to edit that row’s name and MIDI note number inline.
Overridden labels display in the track’s color instead of gray. The override only affects display and MIDI output — saved project files still use the original row names internally, so existing saves load correctly.
Each track panel has a volume slider, a pan slider and a
mute button (M).
M to silence the track. The grid dims to 35% opacity when muted.Volume and mute state are saved per-track and persist across sessions.
Every track plays to exactly one output, chosen from the OUT menu in its header. Nothing is global: there is no master synth or MIDI switch, and a track never plays to two places at once.
| OUT | What plays |
|---|---|
| SYNTH | The track’s built-in Tone.js instrument: the default for the melodic tracks, and a set of percussive voices for a drum track you switch over. |
| Sampler → a kit or keygroup | Samples from the shared library, tagged in Waverly. Drum tracks start here on the 808 style starter kit, which is fetched into your browser’s storage the first time it is needed; the menu also lists the other starter kits under “Starter kits (fetched on pick)”. The drum grid's rows become the kit's pads: KICK / SNARE shows the kick, snares, hats and cymbals, PERCUSSION the toms, congas and the rest. Any row that still has notes but is not in the kit stays, struck through and silent, until you clear it or add that sound to the kit in Waverly. On SYNTH or MIDI the grids show their standard General MIDI rows. On a melodic track a group plays as a keygroup: a sample with a root note set in Waverly covers its key range at exact pitch, and a sample with no root note is assumed to be C4 and stretched across the whole grid, polyphonic either way. |
| MIDI | Notes go to every default MIDI output ticked in the transport bar. A port selector (to pin this track to one output), a channel selector and a patch field appear next to the menu. |
Want a kit and a hardware synth on the same part? Use two tracks with the same pattern (alt-click a slot tab to copy it).
Kits are built and edited in Waverly, the sample editor served beside LJam: the WAVERLY link in the transport bar and “Edit kits in Waverly…” at the bottom of the OUT menu open it in its own tab. Both apps share one browser sample library, so a kit tagged there appears in the OUT menu here when you come back to this tab.
| Track | Default Channel |
|---|---|
| Kick / Snare | 10 (GM Drums) |
| Percussion | 10 (GM Drums) |
| Bass | 2 |
| Lead Synth | 3 |
| Pad / Chords | 4 |
| Arp / FX | 5 |
A device that is unplugged shows as (missing) in red; a track whose outputs are all missing plays silence until one returns or you pick another. The light next to the outputs select is green while some track is sending to a connected device. Pinned ports are saved with the project by id and name; the default set is not.
A track routed to MIDI has a PC / patch text field next to its channel selector. It sends a MIDI Program Change (with optional Bank Select) whenever you change it, when the track is switched to MIDI, when the project loads, and when the device reconnects.
| Input | What it sends | Example use |
|---|---|---|
42 |
CC#0=0, CC#32=0, PC 42 | GM program 42 (bank reset to 0) |
b:6 p:42 |
CC#0=6, CC#32=0, PC 42 | Bank MSB 6, LSB defaults to 0 |
b:0,3 p:24 |
CC#0=0, CC#32=3, PC 24 | SC-8820: SC-88Pro map, Nylon Guitar |
Slap Bass |
Nothing (label only) | Just a reminder for yourself |
The field border highlights in the track color when the value is a valid program number or bank+program pair. Every valid patch change sends the full CC#0 (MSB) + CC#32 (LSB) + Program Change sequence, so switching from a banked patch back to a plain number always resets to bank 0,0.
GS devices like the Roland SC-8820 use CC#32 to select between sound maps:
| LSB | SC-8820 Sound Map |
|---|---|
| 0 | SC-8820 native |
| 1 | SC-55 |
| 2 | SC-88 |
| 3 | SC-88Pro |
The b:MSB,LSB p:N format lets you address these directly.
The short form b:N p:N defaults LSB to 0, which is the
native map — identical behavior to plain GM devices where LSB is
ignored.
Press ↑ / ↓ while the patch field is focused to increment or decrement a value. The cursor position determines which number is affected — place the cursor on the bank MSB, the LSB, or the program number and arrow keys will adjust that part (clamped to 0–127).
b:0 p:0 for the default bank, b:64 p:0 for
variation sets, or b:0,3 p:0 to access the SC-88Pro sound map.
See the GM / GM2 / GS Reference for the
full program list, drum map, and bank select details.
| Action | Shortcut |
|---|---|
| Play / Stop | Space |
| Undo | Ctrl+Z / ⌘+Z |
| Redo | Ctrl+Shift+Z / ⌘+Shift+Z / Ctrl+Y |
| Action | Shortcut |
|---|---|
| Stamp: Whole (16 steps) | W |
| Stamp: Half (8 steps) | H |
| Stamp: Quarter (4 steps) | Q |
| Stamp: Eighth (2 steps) | E |
| Stamp: Sixteenth (1 step) | S |
| Velocity level (1=soft … 0=full) | 0–9 |
| Shift hovered row left/right | ← / → |
| Move hovered note up/down | ↑ / ↓ |
| Shift entire pattern left/right | Shift+← / → |
| Shift all notes up/down (wraps) | Shift+↑ / ↓ |
| Randomize hovered row | R |
| Exit stamp/velocity mode / clear selection | Escape |
Press a stamp key to enter stamp mode (a colored chip appears in the header). Press the same key again or Escape to exit. On melodic grids, clicking an empty cell places a note of that duration. On drum grids, note length is always 1 step — stamp mode only affects the spacing of drum rolls when dragging. If stamp mode is active when pressing R, notes snap to that duration’s grid.
Velocity levels work the same way: press a number key (1–9, 0=10) to set the velocity for new notes. A “v5”-style chip appears in the header. Press the same key or Escape to clear. Velocity maps to MIDI 25–127 and scales the internal synth volume. Duration and velocity can be active simultaneously. Notes without a velocity level use the track volume as before.
Shortcuts are disabled when a text field, select dropdown, or editable element is focused.
Your project is automatically saved to localStorage after every change (500 ms debounce). It reloads automatically when you reopen the page.
Click SAVE in the transport bar to export your project as
a .json file. On Chrome and Edge this opens a native file
dialog; other browsers download the file directly.
Click LOAD to import a previously saved .json
file. The file format is versioned and older saves are automatically
migrated.
Both the per-track randomize button and the RANDOM ALL button use a press-and-hold mechanic:
An undo snapshot is taken when you press down, so Ctrl+Z / ⌘+Z reverts the entire fill in one step.
Per-track randomize and clear buttons affect only the current editing slot for that track.
When sending MIDI on channel 10, drum tracks use these General MIDI note assignments:
| Instrument | Note | MIDI # |
|---|---|---|
| Kick | C1 | 36 |
| Snare | D1 | 38 |
| Closed Hi-Hat | F#1 | 42 |
| Open Hi-Hat | A#1 | 46 |
| Crash Cymbal | C#3 | 49 |
| Ride Cymbal | D#3 | 51 |
| Instrument | Note | MIDI # |
|---|---|---|
| Hand Clap | D#1 | 39 |
| Side Stick / Rim | C#1 | 37 |
| Low Tom | G1 | 43 |
| High Tom | D2 | 50 |
| Conga High | D#3 | 63 |
| Conga Low | E3 | 64 |
| Cowbell | G#2 | 56 |
While the transport is playing, LJam sends MIDI clock messages to every device that any track is routed to:
| Message | Hex | When Sent |
|---|---|---|
| Start | 0xFA | Transport starts playing |
| Timing Clock | 0xF8 | 24 times per quarter note (continuous) |
| Stop | 0xFC | Transport stops |
External apps and hardware can use these messages as a tempo and beat reference. The clock rate adjusts automatically when you change BPM.
LJam doesn’t load SoundFont files directly, but you can use an external SoundFont player to get high-quality GM instrument sounds driven by LJam’s sequencer via MIDI.
Use the patch field on each track to send Program Change messages. The SoundFont player will switch to the corresponding GM instrument. For example:
0 — Acoustic Grand Piano32 — Acoustic Bass80 — Square Leadb:8 p:0 — Bank 8, Program 0 (bank variations)brew install fluidsynthfluidsynth -a coreaudio -m coremidi /path/to/FluidR3_GM.sf2If things get into a strange state — unexpected drum mappings, stuck settings, or corrupted project data — you can wipe all saved state and start fresh.
This clears: