Alesis Quadraverb SysEx reference

This is a working reference for the MIDI System Exclusive implementation of the Alesis Quadraverb and Alesis Quadraverb Plus, written from the implementation behind the QVERB editor rather than transcribed from the manual. It covers the three opcodes the unit understands, the two different bit packings it uses, the 128-byte program layout, and the value convention that trips up most first implementations.

Message frame

Every message shares the same envelope:

F0 00 00 0E 02 <opcode> <data...> F7

00 00 0E is the Alesis manufacturer ID and 02 is the Quadraverb device ID. All data bytes are 7-bit, as MIDI requires — which is the reason for the packing schemes below.

Opcode 0x01 — parameter edit

F0 00 00 0E 02 01 <function> <page> <v1> <v2> <v3> F7

A single parameter change, applied to the edit buffer and audible immediately. The function selects the effect block and the page selects the parameter within it.

FunctionBlock
1Reverb
2Delay
3Pitch
4EQ
7Configuration
8Mix
9Modulation
10Name

The value is a 16-bit quantity spread across three 7-bit bytes. Note that this is not a plain MSB/LSB split — the bits are shifted, so a naive value & 0x7F / value >> 7 encoding sends the wrong number:

v1 = (lsb >> 1) & 0x7F
v2 = ((lsb & 0x01) << 6) | ((msb >> 2) & 0x3F)
v3 = ((msb & 0x03) << 5) & 0x7F

Opcode 0x02 — data dump

F0 00 00 0E 02 02 <program> <packed data...> F7

The unit sends this in reply to a dump request, and accepts it to write data back. The program byte selects what the payload contains: 0–99 for a stored program, 100 for the edit buffer, and any value above 100 for the whole bank.

ScopeOn the wireUnpacked
Single program147 bytes128 bytes
All 100 programs14,629 bytes12,800 bytes

Dump packing is a bitstream, not byte pairs

Dumps use a different scheme from parameter edits: seven 8-bit source bytes become eight 7-bit MIDI bytes, as one continuous 56-bit bitstream shifted out in 7-bit groups. Treat it as a bitstream and both directions become trivial:

// unpack 8 MIDI bytes -> 7 data bytes
let bits = 0n;
for (const b of packed) bits = (bits << 7n) | BigInt(b & 0x7f);
const out = [];
for (let shift = 48n; shift >= 0n; shift -= 8n)
  out.push(Number((bits >> shift) & 0xffn));

A bank dump is just this repeated: 12,800 data bytes as 1,829 groups. If your decoded program names look like shifted gibberish, the bitstream alignment is off by a group, not the byte order.

Opcode 0x03 — dump request

F0 00 00 0E 02 03 <program> F7

Same program selector as opcode 0x02. Requesting 100 returns the edit buffer, including changes not yet stored to a slot — the fastest way to read what a unit is currently doing, and the basis of the backup workflow.

Program data layout

Each program is 128 bytes. Offsets are relative to the start of the program, and the blocks sit at fixed addresses regardless of which configuration is active:

OffsetContents
0x00–0x0CEQ — low, mid and high frequency, bandwidth and amplitude. Reused as graphic-EQ bands in the graphic configuration.
0x1A–0x21Pitch — mode, input, LFO waveform, speed, depth, feedback, detune.
0x27–0x2FDelay — mode, input, input mix, left/right time and feedback.
0x32–0x41Reverb — mode, inputs, pre-delay, decay, diffusion, density, gate.
0x44–0x4AConfiguration, mix routing and per-block output levels.
0x50–0x67Eight modulation slots: source, target, amplitude.
0x6A–0x77Program name, 14 characters.
0x78–0x7BPlus-only extras: ring mod mixes, pan speed and depth.
0x7C–0x7FUnused.

Why some addresses have two names

The configuration byte at 0x44 reinterprets several fields. In the graphic-EQ configuration the EQ block's frequency and amplitude bytes become fixed-band levels (16 Hz, 32 Hz, 62 Hz and so on); in the resonator configuration the pitch LFO depth byte becomes resonator decay. Decode the configuration byte first, then interpret the rest — a parser that reads addresses unconditionally will produce plausible but wrong values on non-default configurations.

ValueConfiguration
0EQ → Pitch → Delay → Reverb
1Leslie → Delay → Reverb
2Graphic EQ → Delay
35-band EQ → Pitch → Delay
43-band EQ → Reverb
5Ring Mod → Delay → Reverb
6Resonator → Delay → Reverb
7Sampling

Values are offset binary

This is the detail that makes an otherwise correct implementation sound wrong. Parameters are stored as offset binary, not two's complement: a control displayed as −99…+99 is stored as 0…198, with 99 meaning zero. Convert on the way in and out:

const toStored  = (shown, min) => shown - min;
const toDisplay = (stored, min) => stored + min;

Symptom of getting it wrong: gains that jump to an extreme at the midpoint of the range, and negative values that wrap to maximum.

Practical notes

Related: backing up your patches, using a unit with a dead display, and Web MIDI setup. For manuals and archive material about the wider Alesis effects line, see quadraverb.nl.