Firmware

mvave-irbox-tools

Hype23/100

Unofficial open-source editor and reverse-engineered protocol docs for the M-VAVE IR Box cab simulator over USB-MIDI: backup, IR upload/export, EQ, volume, presets.

mvave-irbox-tools is custom firmware for the M-VAVE IR Box, by @marco-jardim. Open source under MIT, 1 star on GitHub.

forM-VAVE IR Box·by@marco-jardim

Unclaimed. Is this yours? Sign in with GitHub as @marco-jardim to claim it.

Downloads
0
Star
1
Forks
0
Commits
11
Last commit
Get the source

No release files yet. Build from source.

MIT· marco-jardim/mvave-irbox-tools·downloads come from the creator’s GitHub releases

11
Commits
0
Releases
11 commits and 0 releases in the last year
Activity · last 12 months

mvave-irbox-tools

Unofficial, open-source editor and toolkit for the M-VAVE IR Box cab-sim pedal over USB-MIDI. It reads and edits presets, uploads impulse responses, adjusts EQ and volume, and backs up and restores all 32 slots from a PC, without the vendor app.

Not affiliated with or endorsed by M-VAVE / Cuvave. Use at your own risk.

Status

The protocol is fully mapped and verified on the real device (firmware IR-BOX_010, Windows, USB-MIDI). That covers framing, read/write/ACK, the address map, the preset and EQ layout, refresh modes, select/save and persistence. Audio effects (IR byte order, volume law, EQ units) were confirmed by recording the device's USB audio output. See docs/protocol.md and docs/probing-log.md.

BLE is implemented from the Android app's code but untested: the unit was never seen advertising on Windows.

Features

  • Device query, active slot, name table, full preset dump (JSON, raw binary, IR as WAV).
  • Backup of all 32 slots and restore (whole backup or selected slots).
  • Live edits to the working copy: select slot, volume, cab on/off, EQ on/off, per-band EQ (HPF, low shelf, 5 peaks, high shelf, LPF), and loading an IR, all audible immediately.
  • Persistent operations: save, rename, upload an IR to a slot. Each requires --yes and makes an automatic backup first.
  • IR converter: any PCM 16/24/32-bit or float WAV at any sample rate → 44.1 kHz, 2048 samples, 24-bit LE, normalized to full scale like the factory IRs.
  • Low-level probing tool with a write allowlist, plus audio measurement and A/B scripts.
  • Protocol logic is pure Python and unit-tested (no device needed for pytest).

Setup

Requires Python 3.11+ and uv. Tested on Windows.

uv sync                      # core: python-rtmidi, bleak
uv sync --extra measure      # optional: numpy + sounddevice for scripts/measure.py
uv run pytest

Before running anything, close other MIDI applications (CubeSuite, DAWs, MIDI monitors). On Windows a WinMM MIDI port can be open in only one process at a time. A leftover process causes MidiInWinMM::openPort: error creating Windows MM MIDI input port.

Usage

uv run python scripts/irbox_tool.py [global options] <command> [args]

Global options: --transport midi|ble (default midi), --midi-in, --midi-out (port index or name substring; default is the first port whose name contains USB-Midi), --trace FILE (JSONL log of every frame).

Slot numbers are 1–32, as on the pedal's display. On the wire they are 0–31.

Read-only

uv run python scripts/irbox_tool.py midi-ports            # list MIDI ports
uv run python scripts/irbox_tool.py scan                  # BLE scan
uv run python scripts/irbox_tool.py query                 # device name/firmware (IR-BOX_010)
uv run python scripts/irbox_tool.py info                  # active slot + all slot names
uv run python scripts/irbox_tool.py dump --out dumps/now  # working copy: preset.json, preset_raw.bin, ir.wav, names.json
uv run python scripts/irbox_tool.py backup backups/manual # every slot + name table
uv run python scripts/irbox_tool.py backup backups/fast --raw  # same files, read from the raw flash window (~8 s, no slot switching)
uv run python scripts/irbox_tool.py factory-list path/to/CubeSuite/bin/BOR.bin --compare  # factory image vs device
uv run python scripts/irbox_tool.py ir-export --slot 24 matchless.wav

backup and ir-export of a non-active slot must select that slot to read it. The tool captures the active slot's working copy first and puts it back afterwards (without saving), so unsaved edits survive a backup.

Backup files use 0-based protocol indexes (slot_00.bin = display slot 1); manifest.json records both numberings and a checksum per slot, which restore verifies. In dump, preset.json has slot (display, 1–32) and slot_index (protocol, 0–31). --chunk sets the read size (1–1000, default 1000).

Working copy (not saved)

These commands change the RAM working copy of the active preset and send the matching refresh, so the change is audible at once. Nothing is written to flash. Selecting another slot reverts them, and they are not expected to survive a power cycle.

uv run python scripts/irbox_tool.py select 24
uv run python scripts/irbox_tool.py volume 60                 # 0-127, linear amplitude
uv run python scripts/irbox_tool.py cab off
uv run python scripts/irbox_tool.py eq on
uv run python scripts/irbox_tool.py eq-band hpf --freq 80 --enable
uv run python scripts/irbox_tool.py eq-band peak2 --freq 400 --gain -3.5 --q 1.4 --enable
uv run python scripts/irbox_tool.py eq-band highshelf --freq 6000 --gain -2 --enable
uv run python scripts/irbox_tool.py eq-band lpf --disable
uv run python scripts/irbox_tool.py ir-load my_cab.wav --channel left --trim-silence

eq-band BAND accepts hpf, lowshelf, peak1…peak5, highshelf and lpf, with --freq HZ, --gain DB (±12 dB in 0.1 dB steps), --q Q (0.1–16), and --enable / --disable. Bands only take effect while eq on. ir-load does not turn the cab on; it warns if the cab is off.

Factory presets

M-VAVE's factory image is bin/BOR.bin inside the official CubeSuite download (Windows/macOS). This project does not redistribute it. factory-restore writes it back slot by slot through the normal save path. It never uses the erase command or raw flash writes, which the official app does use. See docs/firmware.md.

uv run python scripts/irbox_tool.py factory-restore path/to/BOR.bin --yes            # only slots that differ
uv run python scripts/irbox_tool.py factory-restore path/to/BOR.bin --slot 1 --yes   # one slot

Persistent (writes flash)

Each of these requires --yes. Each first writes an automatic backup to backups/<timestamp>/, unless --no-backup is given.

uv run python scripts/irbox_tool.py save --name "My Cab" --yes        # save working copy to the active slot
uv run python scripts/irbox_tool.py rename --slot 32 "Bass DI" --yes
uv run python scripts/irbox_tool.py ir-upload my_cab.wav --slot 32 --name "My Cab" --yes
uv run python scripts/irbox_tool.py restore backups/20261008-191500 --yes            # all slots
uv run python scripts/irbox_tool.py restore backups/20261008-191500 --slot 32 --yes  # one slot

save always targets the active slot. rename and ir-upload start from the target slot's stored flash contents (unsaved edits on that slot are lost) and leave the target slot active. ir-upload also turns the cab on.

IR conversion options (ir-load, ir-upload)

OptionMeaning
--channel mix|left|righthow to reduce multichannel files to mono
--normalize peak|nonepeak-normalize to full scale (default peak, like the factory IRs) or keep the level
--peak-db DBtarget peak for --normalize peak
--gain-db DBextra gain
--fade Nlength in samples of the raised-cosine fade-out applied when the IR is truncated
--trim-silencedrop leading silence before taking the first 2048 samples

Pipeline: read any PCM int 16/24/32 or float WAV at any rate → Kaiser windowed-sinc resample to 44.1 kHz → keep the first 2048 samples (46.4 ms), with a raised-cosine fade if truncated → normalize → signed 24-bit LE. The official app's converter has known bugs: 16-bit IRs end up about 48 dB too quiet, and 48 kHz files are not resampled. See docs/apk-analysis.md.

Safety

  • Working copy vs flash. Every edit goes to a RAM working copy and is lost on slot change, until it is saved. Only save, rename, ir-upload and restore write flash.
  • Automatic backup. Persistent commands back up every slot to backups/<timestamp>/ first. A backup/restore round trip was verified byte-identical on the device.
  • Explicit confirmation. Persistent commands do nothing without --yes.
  • Never erase, never OTA. Command 0x21 (erase) is refused on every transport. The BLE OTA characteristics (ae00/ae01/ae02) are never touched. There is no firmware-update feature.
  • Keep backups/. It holds your only copy of the content that shipped on your unit. Keep it outside version control and do not publish it, since the factory IRs are M-VAVE's content.
  • The device does not reject reads or writes to unmapped addresses (see docs/protocol.md quirks). Use the CLI rather than hand-made frames.

Scripts

ScriptPurpose
scripts/irbox_tool.pyThe CLI above.
scripts/irbox/Library: protocol (frames, SysEx 8→7 packing, parsers, denylist), midi (python-rtmidi transport), ble (bleak transport), model (preset and name-table decoding), wav (IR conversion and WAV I/O).
scripts/probe.pyLow-level probing: read TYPE ADDR LEN, regions, monitor SECONDS, poll SECONDS [--full], query [CODE], irtest same|dirac|dirac-be|dirac-full|scale-le|scale-be [--refresh], backup DIR, save SLOT_INDEX --yes-flash, write TYPE ADDR HEX --yes. write is limited to an allowlist: type 5 0x11, 0x12, 0x2B, 0xA0000000, the EQ range 0x1C00–0x1C27, and slot select (type 4 0xE0000000+i). probe.py uses slot indices 0–31.
scripts/measure.pyUSB audio measurement: sweep loopback and record-only band report. See docs/measurement.md.
scripts/sequence_volume_eq.ps1, sequence_eq_bands.ps1, sequence_eq_units.ps1Scripted A/B recordings of volume and EQ changes on the working copy (never save).

Docs

DocumentContent
docs/protocol.mdCanonical protocol: framing, commands, address map, preset and EQ layout, refresh, select/save, quirks, worked hex examples
docs/usb.mdUSB identity, MIDI ports, SysEx wrapping and 8→7 packing, sizes and timing
docs/protocol-ble.mdBLE GATT transport (from app code, untested)
docs/hardware.mdControls, display, USB audio path, headphone notes, content found on the unit
docs/measurement.mdHow the audio measurements and A/B tests work, and their limits
docs/probing-log.mdDated log of the device probing sessions
docs/apk-analysis.mdHow the protocol was recovered from the official app, and the app's converter bugs
docs/firmware.mdFirmware search results, update tooling and .fwsc container, chip, fix opportunities
docs/flash-dump.mdRunbook for a read-only flash dump via JieLi USB download mode (not performed)

License

MIT, see LICENSE.

Credits

The SysEx packing and the idea that M-VAVE devices carry the 00 59 frames in SysEx come from community work on related devices: