mpc-vst-monomodule, image 1 from its README
1/4
Firmware

mpc-vst-monomodule

Loud92/100

Monomodule (Monomachine DSP56300 emulation) as an Akai Force/MPC OS VST2 plugin, via mpc-vst-plugins

mpc-vst-monomodule is custom firmware for the Akai Professional MPC Live, by @sd88me. Open source under AGPL-3.0, latest release v1.0.4 (November 2026), 18 stars on GitHub.

forAkai Professional MPC Live·by@sd88me

Unclaimed. Is this yours? Sign in with GitHub as @sd88me to claim it.

Downloads
0
Stars
18
Forks
3
Commits
127
Last commit
Download v1.0.4

Monomodule-One-1.0.4-mpc-aarch64.zip· 4.2 MB· +1 file

AGPL-3.0· sd88me/mpc-vst-monomodule·downloads come from the creator’s GitHub releases

100
Commits
8
Releases
100 commits and 8 releases in the last year
Activity · last 12 months

Monomodule for MPC OS

💬 Questions or feedback? Join the Open MPC Discord.

MPC OS. This release works on MPC OS 3.x. On MPC OS 2.x it loads and plays from the Q-Links, but its touchscreen page stays empty until a release with a compatible skin is published. The catalog shows which MPC OS each release works on, and the installers warn before putting a 3.x-only plugin on a 2.x device. See MPC OS 2.x vs 3.x in the main repo.

Monomodule — a chip-accurate emulation of the Elektron Monomachine's synth engine — as native VST2 plugins for Akai MPC OS standalone devices (MPC Live/One/X/Key, Force). Monomodule One is the instrument (15 synth machines); Monomodule FX is the same engine's 7 effect machines as an audio effect. Both load in MPC's built-in plugin host with their own touchscreen skins and Q-Link support.

Current release: v1.0.0 for Gen2 (MPC Live III and kin), a normal download with nothing of Elektron's in it (see "Gen2" below), now with a poly mode. The Force (Gen1, v0.10.2) has no downloadable build (see "Install" below for why); build it yourself from your own OS file with release/release.sh (one command; release/build_from_os.sh is its build step).

An MPC port by sd88me of shnolk's Monomodule engine (all credit for the emulation to shnolk; see Credits). Listed in MPC under the manufacturer sd88me, since shnolk neither makes nor supports this port: report problems here, not to shnolk. Not affiliated with Elektron or with shnolk. Requires your own Monomachine OS file (see below); nothing of Elektron's is included or distributed.

2026-09-30T112857523Z

New in 0.10.2: a reloaded project, clip or autosampler pass keeps your sound. MPC probes the machine parameter (sets another value, then straight back) around project load, clip play and the autosampler, and each machine change reset the pages, wiping the restored patch. The plugin now puts the replaced sound back when its machine returns within half a second.

New in 0.10.1: saving and reloading now keeps your patch. Before, a saved MPC project, program or plugin preset came back as the Init sound, because the plugin never handed MPC its state. It now stores every knob, the machine, the preset and bank selection, so a reload restores the sound exactly.

New in 0.10.0: the plugins are listed under the manufacturer sd88me (they were listed as shnolk, who wrote the engine but doesn't make or support this port). Installing renames your old shnolk - VST - Monomodule One/FX folders, so your kit dumps are kept, and replaces the plugin-list entries. The skin no longer carries shnolk's logo: the header reads MONO MODULE and the machine selector lines up with the SYN page.

Why this exists

The Monomachine's sound comes from a Motorola DSP56300 chip, and Monomodule emulates it instruction by instruction — accurate, but too slow for the Force's 32-bit ARM chip to run in real time (the existing dsp56300 JIT compiler only targets x86-64 and 64-bit ARM). Rather than drop the port, we built a static recompiler: it traces every DSP instruction Monomodule's engine actually executes, translates that trace ahead of time into native ARM code, and strips out per-instruction overhead the interpreter can't. The result is bit-exact with the original emulator and runs at roughly the pace the DSP thread needs. The technical detail is at the bottom of this README and in libs/dsp56300/docs/ARM32_JIT.md.

What's a faithful port, and what we added

Faithful to upstream Monomodule (same engine, same numbers, same layout logic):

  • The DSP56300 emulation itself, and Monomodule's own host model (parameter block, LFOs, key tracking, master tune) — unmodified upstream code.
  • Every machine's knob layout, labels, default values and bipolar/list/readout display types (SYN A–H, AMP, FILT, EFX, LFO1–3) come straight from upstream's UI spec.
  • The skin's LCD art — fonts, dial, list icons, machine-group logos — is drawn from your own Monomachine OS file using upstream's own art-reading code, the same way the JUCE plugin does. It's not our artwork; it's the hardware's, reproduced exactly.
  • The machine picker (grouped by GND/SID/SWAVE/DPRO/FM+/VO, with the same blurbs) and the PREV/NEXT preset stepper follow upstream's own editor design.

Added for this port (not in upstream Monomodule, or done differently because MPC's plugin format requires it):

  • Whole-cell touch. Upstream draws a small dial per cell; here, the whole cell (minus a small edge margin) is the drag target, since MPC's touchscreen knobs are much larger than a mouse pointer.
  • Layout choices (layout=tabs|2x2|grid in vst/skin/skin.conf) and colour presets (mnm, the default: the real unit's soft cool-grey LCD with near-black pixels, matched to a photo of the hardware; upstream's default/inverted/low-contrast; and red/blue/green/orange and their inverted forms) — upstream is a fixed-size JUCE window; MPC's screen and skin format need a purpose-built layout.
  • A hardware-style chassis for the default 2x2 layout: a brushed-aluminium faceplate and thin bezel around one LCD whose left and right edges sit a fixed margin (lcd_margin=28 px) outside the page panels.
  • Bank and preset lists (Gen2 build): tap the BANK or PRESET field and a list opens with the names of your own dumps and sounds, 24 to a page (PREV/NEXT page for presets); the arrows still step. Upstream has a full scrollable library browser; MPC's plugin skins can't change a list's length at run time, so these are fixed 24-slot lists whose names are live text (see "Presets and banks" below).
  • Native Q-Link outlines: MPC outlines (orange box with a Q) the four knobs the Q-Links currently drive, one box per Q-Link column.
  • Three randomise buttons (RND SYN, RND A/F, RND LFO) — not in upstream at all.
  • Master tune and LPF/HPF key-tracking controls exposed on-screen — upstream's engine supports both, but its own One editor doesn't expose them as knobs; we did, in the spare space next to LEV.
  • The factory kit bank, recovered from an undocumented section of the OS file and made available as an ordinary preset dump (see below) — upstream's own tools don't do this.
  • Monomodule FX as a separate effect plugin — upstream's FX machines only run inside the full One/Six instrument; here they're a standalone insert effect.

Presets and banks

Presets are machine-specific: PREV/NEXT only steps through sounds that use whichever machine is currently selected on SYN. Switching machine changes what PREV/NEXT shows.

Where sounds come from:

  • INIT — the current machine's own defaults, always first.
  • Any Monomachine kit dump (.syx) you place in either watched folder: /sdcard/Synths/sd88me - VST - Monomodule One/monomodule/dumps/ (SD card / SSH) or /sdcard/Force Documents/Monomachine Dumps/ (MPC's own file browser). Both are scanned every few seconds — no reinsert needed. A kit dump has up to 6 tracks; each track becomes one preset for whichever machine that track uses, so one kit can contribute several presets across several machines.
  • The factory kit bank, extracted from your own OS file (see "The factory bank" below) and dropped into the dumps folder like any other dump.

The BANK stepper (above PRESET) narrows this to one .syx file at a time; its default, "ALL", pools everything together as before. A * after a preset's name means you've edited it since loading.

Tap the BANK or PRESET field to open a list (Gen2 build): bank names (the first 24), or this machine's sounds in the selected bank, 24 per page with PREV/NEXT. A pick loads it and closes the list; tap the field again to close without picking. The current one is outlined. Both lists share the same screen area, so close one before opening the other. The list's names are live text, so a new dump shows up as soon as the plugin rescans; a bank list longer than 24 only shows the first 24 (the arrows reach the rest).

The factory bank

The Monomachine OS file turns out to hold its factory kit bank in an undocumented section of the firmware image, in exactly the byte layout Monomodule's own kit-dump decoder already understands. vst/skin/extract_factory.sh <your-os.syx> <out.syx> pulls it out and re-encodes it as an ordinary kit dump — about 77 named kits, covering every machine. This is Elektron's own content extracted from your own file: the generated .syx is never committed, distributed or included with this repo.

Gen2 (MPC Live III and kin, 64-bit): a normal download

Gen2 MPCs run a 64-bit userland, and there the dsp56300 JIT works as it is: no recompiling, nothing derived from your OS file inside the plugin. So on Gen2 Monomodule is an ordinary plugin download (Monomodule-One-<version>-mpc-aarch64.zip and Monomodule-FX-<version>-mpc-aarch64.zip, from the catalog or the releases page), with nothing of Elektron's in it.

  1. Install the zip(s) like any plugin (the catalog's installer, or install.sh inside the zip, as root on the device).
  2. Put your own Monomachine OS file, named Elektron_SFX6-60_OS1.32B.syx, in the plugin's monomodule/ folder in your Synths folder (on a Live III that is /nvme/Synths/sd88me - VST - Monomodule One/monomodule/). One copy serves One and FX. The installer app's Your ROMs and files step can do this for you: it checks each file before copying it into the right folder and saves it under that name, whatever it is called on your computer (rules: release/userfiles.json).
  3. Load the plugin once, then restart MPC. On that first load the plugin makes its skin from the OS file's own LCD artwork (a recipe in the zip says which skin pixel follows which bit of the art, so the skin is exactly the Gen1 one), and it plays from then on.

Monomodule One on an MPC Live III The preset list: 32 sounds a page, from your dumps Monomodule FX on an MPC Live III

Tap BANK or PRESET to open the lists (24 banks and 32 sounds a page, PREV/NEXT page); MPC outlines the four knobs the Q-Links drive.

Poly mode (Gen2 only). The VOICES knob on the GLOBAL page (LFO tab, second page; also a Q-Link) runs 1 to 6 copies of the synth engine. All voices play the instrument's current sound; VOICES only decides how incoming notes are spread over them (the same note retriggers its voice, then the oldest free voice, otherwise the oldest is stolen). At 1 it behaves exactly as before. The extra voices are built in the background a few seconds after you raise VOICES. Each voice costs about one more DSP-thread's worth of CPU on a Live III (six DDRW voices: about 1.8 cores); the Force stays at 1 voice. Output level is 6 dB hotter than 0.11 and the mix is scaled by the voice count^-1/4.

The JIT is bit-exact with the interpreter on all 22 machines (release/build_gen2.sh checks this, on emulated arm64, before it packages). Tested on an MPC Live III (v1.0.0): installed from the zips, skin made from the OS file, lists, preset loads and POLY playing from the pads work. The plugin's own paced render test, with MPC running alongside: One uses 24-45% of its DSP thread depending on the machine, FX 29-43%, and neither underran on any machine. Other Gen2 models are untried. The catalog ids are monomodule-one-gen2 and monomodule-fx-gen2. To build it yourself: release/build_gen2.sh <your-os.syx> (needs Docker; about 40 minutes, most of it the skin-recipe check).

Requirements

  • A first-generation MPC OS standalone device (32-bit ARM: Force, MPC Live/Live II, One, X, Key 61), or a Gen2 one (see above). Tested on a Force running MPC OS 3.9.1 (see tested.json).
  • Root SSH access. Installing plugins this way is unofficial: back up first, use at your own risk.
  • Your own Monomachine OS file (tested against OS 1.32B), and optionally any Monomachine kit .syx dumps you want as presets. Not included; a free download from Elektron.

Install

On Gen1 (32-bit ARM) there is no download. (Gen2 has one: see above.) The DSP is static-recompiled ahead of time from your own OS file (see "Why this exists"), and that recompiled code ends up inside the plugin. So every build is personal: you build it from your own OS file, and the result is yours alone to install, never to redistribute.

Where things happen: the build runs on your own computer (macOS, Linux, or Ubuntu inside WSL on Windows), not on the Force. The Force only receives the finished plugin. You don't need to be a programmer: follow the steps in order and run the check after each one. (The site's Build page has the same computer setup with more detail, and the general build-it-yourself process.)

Step 1: Get your files and your device's address

  1. Download the Monomachine OS 1.32B .syx file from Elektron's website (free) and put it in a folder you can find, for example ~/mono/. Keep the path free of spaces.
  2. Find your device's IP address (on the Force/MPC: Menu, Preferences, Network; it looks like 192.168.1.44). The device and your computer must be on the same network.
  3. Make sure SSH works. In a terminal run ssh root@<device-ip>. If it asks for a password or logs you in, you're set (type exit to leave). If it times out, see "Check that you can reach your device" on the Install page.

Step 2: Set up your computer (one time)

  1. Open a terminal. macOS: the Terminal app. Ubuntu: Ctrl+Alt+T. Windows: install Ubuntu in WSL 2 (wsl --install in an administrator PowerShell, restart, open "Ubuntu") and run everything below inside it, in your Ubuntu home folder (cd ~).
  2. Install git. Ubuntu/WSL: sudo apt update && sudo apt install git. macOS: xcode-select --install. Check: git --version prints a version.
  3. Install Docker (Docker Desktop on macOS/Windows, and start it; Docker Engine on Ubuntu, then sudo usermod -aG docker $USER and log out and back in). Check: docker run --rm hello-world prints a welcome message.
  4. Have about 10 GB of free disk space (Docker images) for the first build.

Step 3: Build and install

  1. Get the source:
    git clone --recursive https://github.com/sd88me/mpc-vst-monomodule.git
    cd mpc-vst-monomodule
    
  2. Save your project on the device, then build and install in one command (about 5 minutes; the first run downloads more). Put the path to your OS file in quotes:
    release/release.sh "/path/to/your-monomachine-os.syx" -d <device-ip>
    
  3. Watch the output. It stops at the first error and says which step failed. The build runs a bit-exactness check against the reference emulator first; if it fails, nothing is built for the device (your OS file or toolchain differs from what this was tested with).
  4. When it finishes, the installer has copied the plugin over, backed up MPC.settings, and restarted MPC once.

Step 4: Use it

On the device, add Monomodule One (Instrument plugins) or Monomodule FX (Insert effects) to a track; both are listed under the manufacturer sd88me. Save and reload a project once to confirm your sound comes back.

Alternative: build now, install later

Leave off -d to just make the zip, dist/Monomodule-<version>-mpc-armv7.zip, then install it yourself:

scp -r dist/Monomodule-<version>-mpc-armv7 root@<device-ip>:/tmp/
ssh root@<device-ip> sh /tmp/Monomodule-<version>-mpc-armv7/install.sh

or drop the zip into the installer app. Either way both plugins are installed, MPC.settings is backed up first, and MPC restarts once. release/uninstall.sh reverses it.

If something goes wrong

You seeUsually means
docker: permission deniedYour user isn't in the docker group yet: run the usermod command above, log out and in.
Cannot connect to the Docker daemonDocker isn't running: start Docker Desktop (or sudo systemctl start docker).
ssh: ... timed out / Permission deniedWrong IP, different network, or SSH not reachable; see Step 1.
Stops at the bit-exactness checkWrong OS file or version. Use Monomachine OS 1.32B.

Still stuck? Ask on the Open MPC Discord, pasting the last 20 lines of output.

Options

release.sh picks a version from git describe (or a dated dev version if untagged); pass -v to override, -m <checkout> to use your own mpc-vst-plugins checkout instead of auto-cloning one, and -l <layout> for a non-default skin layout. release/build_from_os.sh + release/package.sh are there individually if you want one step, e.g. while iterating.

Want the factory kit bank as presets too? release/extract_factory.sh <your-os.syx> <out.syx>, then copy the result into /sdcard/Synths/sd88me - VST - Monomodule One/monomodule/dumps/ (see "The factory bank" above).

Plugin catalog

Monomodule is a build-it-yourself plugin: the zip embeds your OS file's recompiled DSP, so it is built per user and must never be published as a release (a catalog entry for it links to this repo and its build instructions, not to a download). The one-command build is release/release.sh (above); device testing is recorded in tested.json (v0.9.0: Akai Force, MPC OS 3.9.1).

Building each piece by hand

release/build_from_os.sh is a thin wrapper around three separate steps, useful individually if you're iterating on one part:

vst/build_so.sh <dir with dsp56k_recomp.inl> <mpc-vst-plugins checkout>
vst/skin/build_skin.sh <your-os.syx> <mpc-vst-plugins checkout> layout=2x2
vst/skin/build_skin.sh <your-os.syx> <mpc-vst-plugins checkout> layout=2x2 fx=1

The first cross-compiles monomodule_one.so and monomodule_fx.so from this repo alone (the cmake/ and CMakeLists.txt at the repo root, libs/monomodule and libs/dsp56300 submodules, and the vendored engine glue in vst/engine/) plus mpc-vst-plugins' wrapper — no external glue tree needed. It builds its own cross-compiler image (tools/Dockerfile.armhf-builder) on first use. <dir with dsp56k_recomp.inl> is your own build of the static recompiler (libs/dsp56300/tools/arm32jit_prototype/recomp/README.md, or let build_from_os.sh run that step for you) — it embeds firmware words and must never be committed or distributed, and neither must the .so files it produces.

Status

One and FX are both running on a real Force, registered in MPC OS, with the exact-upstream skin, whole-cell touch, colour/layout options, bank and preset stepping, randomise, and master tune / key tracking, all confirmed on the device. Bit-exact against the x86 reference emulator on all 22 machines.

Known issue, open: Q-Link nudges on a 0–127 knob can climb a few steps then reset near 0 in MPC's Track Q-Link mode; Screen mode is unaffected. One cause (two interactive components bound to the same parameter, from the whole-cell touch overlay) was found and fixed; whether that's the whole story for Track mode specifically is unconfirmed.

CPU, Monomodule One (Force, one instance, DSP on its own pinned, parking, real-time thread; paced measurement):

MachineDSP-thread load
SWAVE SAW (typical)~46% of one core
DPRO DDRW (heaviest)~69% of one core

CPU, Monomodule FX (noise in, paced):

MachineDSP-thread load
THRU~45%
DYNAMIX~50%
PHASER~54%
FLANGER~60%
CHORUS / RINGMOD~64%
REVERB (heaviest)~70%

Each instance needs its own core — see "Coexistence" in ARM32_JIT.md for what else can share it. About 62 MB per instance.

Background

Monomodule (by shnolk) is a chip-level emulation of the Elektron Monomachine, built on the dsp56300 DSP56300 emulator core. libs/monomodule vendors its engine core (src/core/) unmodified; its own JUCE plugins/app aren't built. vst/engine/ vendors a small, real performance patch to two of that core's files (DspEngine/MonoVoice) from legsmechanical/schwung-monomodule's Ableton Move port of the same DSP core — see vst/engine/VENDORED.md for exactly what and why (a much cheaper block handoff, JIT-preserving reset, prewarm and idle-skip, and idle-loop patching).

libs/dsp56300 is sd88me/dsp56300, forked from the upstream DSP56300 emulator at branch arm32 specifically for the 32-bit ARM static recompiler this port needed; it's independently useful to any dsp56300-based product targeting 32-bit ARM.

The plugin wrapper (wrapper/vst2_wrap.c), build pipeline and skin tooling are shared with the other ports in mpc-vst-plugins; this session added audio-effect support there (for Monomodule FX) and a momentary-button hold-time option (for the randomise buttons' visual feedback), both usable by future ports too.

Technical: the 32-bit ARM static recompiler

Full detail lives in libs/dsp56300/docs/ARM32_JIT.md and libs/dsp56300/tools/arm32jit_prototype/recomp/README.md (the generator pipeline). Short version of what was tried and what worked:

  1. A runtime JIT for 32-bit ARM was ruled out. A hand-written Thumb-2 block compiler, calling into the existing interpreter's opcode handlers, ran only ~1.1–1.17× the interpreter's speed on the Force — under the 1.3× bail-out gate this project set before committing to that approach.
  2. The interpreter's own profile was flat (largest single symbol 10.5% of time, per-instruction dispatch overhead ~31%), so optimising it directly tops out around 1.45× — not enough against the 2.5–4× headroom needed.
  3. Static (ahead-of-time) recompilation worked. mnm-golden's test workload runs on the interpreter once, with a hook recording every executed (PC, opcode) pair (~8,600 distinct instructions, 98.4% of what the workload executes). A generator groups those into ~1,100 basic blocks and emits one C++ function per block that calls the interpreter's own opcode handlers with the opcode baked in as a compile-time constant — letting the compiler inline and constant-fold what the interpreter can't. Blocks are verified against the live P-memory words before running (a self-modifying or unseen program falls back to the interpreter), and invalidated automatically if the DSP writes to program memory.
  4. Dead-flag elimination: where a generated block can prove no later instruction (before the next conditional, branch or CCR read) reads a particular condition-code flag, it uses a flag-skipping variant of that instruction (still correct for saturation, the sticky L bit and carry).
  5. Hot-helper fixes found from an on-device, source-line-attributed profiler: a faster address-register update for the common (non-wrapping) case, faster 56-bit sign extension on a 32-bit target, and a single-comparison peripheral-address check, among others.
  6. Final result: bit-exact with the x86 interpreter on all 22 machines, and real-time on the Force at the loads in the CPU table above — down from 150–285% of a core for the plain interpreter. Further speed-ups (block chaining, mode-bit specialisation, a register-allocating code generator) are catalogued in ARM32_JIT.md but parked for a future revision; today's performance was judged sufficient to ship.

The generated code and the OS file's LCD art both embed Elektron's own firmware/ROM content, so both are built from your OS file at install time and never committed or distributed — see vst/skin/.gitignore.

License

AGPL-3.0-only. See LICENSE. The engine under vst/engine is adapted from legsmechanical/schwung-monomodule (AGPLv3); see vst/engine/VENDORED.md. Nothing of Elektron's is in this repository.

Credits

  • shnolk: Monomodule, the chip-level Monomachine emulation this port is built on.
  • dsp56300 project: the DSP56300 emulator core Monomodule and this port's ARM static recompiler are both built on.
  • legsmechanical: schwung-monomodule, the engine-glue pattern this port's mnm_engine.cpp follows.
  • Elektron: the original Monomachine hardware, OS and factory sound bank (not included; see "Requirements" and "The factory bank" above).
  • sd88me: this MPC OS VST2 port, the arm32 dsp56300 fork, and mpc-vst-plugins.