3 releases
| 0.1.2 | Apr 7, 2026 |
|---|---|
| 0.1.1 | Apr 6, 2026 |
| 0.1.0 | Apr 6, 2026 |
#76 in Audio
Used in minilogue
685KB
15K
SLoC
minilogue-xd
A complete Rust library for the Korg Minilogue XD synthesizer, covering 100% of the MIDI Implementation (Revision 1.01) — CC parameters, NRPN, SysEx program and global data blobs, the 16-step sequencer with motion sequences, sub-cent tuning tables, and user module management for logue SDK units.
The goal: treat the XD desktop module as a voice in an imaginary MIDI-based Eurorack system, with every parameter reachable from Rust in real time.
Install
# Cargo.toml
[dependencies]
minilogue-xd = "0.1"
Requires Rust 2021 edition. The midi-io feature (default on) pulls in midir for live
MIDI port access. Disable it for pure file manipulation or no_std targets:
minilogue-xd = { version = "0.1", default-features = false, features = ["file-formats"] }
Quick start
use minilogue_xd::{
controller::RealtimeController,
param::enums::{VcoWave, VcoOctave, LfoMode, EgTarget, MicroTuning},
transport::MidirOutput,
};
fn main() -> minilogue_xd::Result<()> {
let output = MidirOutput::connect("minilogue xd", 0)?;
let mut xd = RealtimeController::new(output, 0);
// VCO control — natural units, typed enums
xd.set_vco1_wave(VcoWave::Saw)?;
xd.set_cutoff(0.6)?; // 0.0 – 1.0
xd.set_resonance(0.4)?;
xd.set_lfo_rate(0.3)?;
xd.set_lfo_mode(LfoMode::Bpm)?;
xd.set_eg_target(EgTarget::Cutoff)?;
// NRPN: deep parameters not on the CC surface
xd.set_micro_tuning(MicroTuning::Pythagorean)?;
xd.set_bend_range_plus(7)?;
xd.play_note(60, 100)?; // middle C, velocity 100
Ok(())
}
Patch manipulation
use minilogue_xd::{
builder::PatchBuilder,
param::enums::{VcoWave, VcoOctave, CutoffDrive, CutoffKeytrack, DelaySubType},
sysex::transaction::SysexTransaction,
};
// Build a patch programmatically
let patch = PatchBuilder::new()
.name("Acid Bass")
.vco1(VcoWave::Saw, VcoOctave::Eight, 0.0, 0.5)
.filter(0.35, 0.8, CutoffDrive::Full, CutoffKeytrack::Full)
.amp_eg(0.0, 0.3, 0.0, 0.1)
.delay(DelaySubType::Tape, 0.4, 0.6, 0.3)
.build()?;
// Send it to the edit buffer over SysEx
let mut tx = SysexTransaction::new(output, input, channel);
tx.send_current_program(&patch)?;
// Load a .mnlgxdlib file from disk
let patches = minilogue_xd::load_lib_file("factory.mnlgxdlib")?;
println!("{} patches loaded", patches.len());
Sequencer & motion
use minilogue_xd::builder::SequenceBuilder;
use minilogue_xd::param::enums::{StepResolution, ArpRate, MotionParameter};
let seq = SequenceBuilder::new()
.bpm(120.0)
.length(8)
.resolution(StepResolution::Sixteenth)
.swing(15)
.step(0, &[60], &[100], GateTime::Percent(50))
.step(2, &[63], &[80], GateTime::Percent(50))
.step(4, &[60], &[110], GateTime::Percent(75))
.step(6, &[67], &[90], GateTime::Tie)
// Motion: automate cutoff across all 8 steps
.motion_slot(0, MotionParameter::Cutoff, true)
.motion_step(0, 0, &[0.2, 0.4, 0.6, 0.8, 1.0])
.build()?;
Micro-tuning
use minilogue_xd::sysex::tuning::{UserScale, CentOffset};
use minilogue_xd::sysex::transaction::SysexTransaction;
// Build a 128-note user scale
let mut scale = UserScale::equal_temperament();
// Flatten the third by 14 cents (just intonation approximation)
scale.set_note(64, CentOffset(-14.0));
let mut tx = SysexTransaction::new(output, input, channel);
tx.send_user_scale(&scale)?;
Features
| What | Coverage |
|---|---|
| CC parameters | All 50+ with typed enums and 10-bit high-resolution encoding |
| NRPN parameters | All 29 entries, including VPM params and user oscillator params |
| Program blob | Full 1024-byte parse/serialize (TABLE 2), all bit-packed fields |
| Global settings | Full 63-byte parse/serialize (TABLE 1) |
| Sequencer | 16 steps, active steps, motion slots, step events, ARP settings |
| Motion sequences | 4 slots × 16 steps × 5-point interpolation, 45 assignable parameters |
| Micro-tuning | User scale (128 notes, 0.0061-cent precision), user octave (12 notes) |
| MIDI Tuning Standard | Bulk dump and single-note tuning change |
| User modules | Query, upload, download, clear, swap logue SDK OSC/FX slots |
| File formats | .mnlgxdprog, .mnlgxdlib, .mnlgxdpreset, .mnlgxdunit |
| Poly chain | Note on/off SysEx with sub-semitone pitch encoding |
| Transport | Clock, Start, Continue, Stop, Song Position Pointer |
| Device identity | Inquiry request/reply, search device request/reply |
| Real-time control | Fluent API for all CC/NRPN params with float-to-integer mapping |
| SysEx transactions | Request/response flows with timeout and ACK/NAK handling |
| Patch builder | Ergonomic builder for ProgramData (VCOs, filter, EGs, LFO, FX) |
| Sequence builder | Builder for SequencerParams (BPM, steps, gate times, ARP) |
| MIDI file export | Standard MIDI File (Format 0) with patch CCs, automation, and CC legend |
Architecture
minilogue-xd
├── transport MIDI I/O abstraction (midir backend, MockOutput for tests)
├── message Channel, realtime, and common message types
├── codec Korg 7-bit ↔ 8-bit SysEx encoding (NOTE 1)
├── param
│ ├── enums Typed enums for all stepped/discrete parameters
│ ├── encoding 10-bit, 8-bit high-res, and 14-bit parameter encoding
│ ├── cc CC parameter map (50+ parameters)
│ └── nrpn NRPN parameter map and state machine receiver
├── sysex
│ ├── frame Korg SysEx header builder/parser, ACK/NAK status codes
│ ├── identity Device inquiry and search device messages
│ ├── global Global parameter blob (TABLE 1)
│ ├── program Program data blob (TABLE 2): synth + sequencer
│ ├── tuning User scale, user octave, MIDI Tuning Standard
│ ├── user_module logue SDK slot management
│ ├── poly_chain Poly chain note on/off
│ └── transaction Request/response manager with timeout and ACK/NAK handling
├── controller Real-time parameter controller (fluent API)
├── builder PatchBuilder and SequenceBuilder
└── midi_file Standard MIDI File (Format 0) export with CC legend
Feature flags
| Flag | Default | Description |
|---|---|---|
midi-io |
on | Live MIDI I/O via midir |
file-formats |
on | .mnlgxd* file format support (requires zip) |
std |
on | Disable for no_std — codec, message, and param layers remain available |
Community references
This library is built on top of prior community work that validated the spec against
real hardware. The workbench/ directory (not tracked in git) contains clones of:
| Repo | Language | What it contributes |
|---|---|---|
| korginc/logue-sdk | C/C++ | Official Korg SDK — user module binary format, CRC32 |
| gekart/mnlgxd.py | Python | Program blob parser — ground truth for TABLE 2 byte offsets |
| isnotinvain/minilogue-xd-util | Python | Patch object model — sequencer and motion byte layout |
| gazzar/loguetools | Python | Cross-synth patch tools — .mnlgxd* file container formats |
Known documentation errata
The Korg MIDI implementation document (rev 1.01) contains a small number of errors discovered by the community:
- Bank select and program number encoding differs from the spec in practice — the library is validated against real files rather than the documented encoding alone.
.mnlgxdpresetfiles from firmware v2.10+ use 448-byte program blobs, not the 1024-byte format described in the spec. Both formats are supported.
MIDI implementation version
Covers Korg Minilogue XD MIDI Implementation Revision 1.01 (2020.02.10). Works with both the keyboard variant and the desktop module variant.
Examples
The examples/ directory contains runnable demos:
list_ports— Enumerate available MIDI output portstest_drive— Connect to the XD, set up a pad sound, and play a chord progressionberlin_school— Tangerine Dream–style Berlin School sequencer with evolving filter sweeps, tape echo, key modulation (E minor → C minor → E minor), and velocity fadeexport_midi— Export the Berlin School sequence as a Standard MIDI File (.mid) with patch CCs, cutoff automation, and a CC legend text file — ready for notation software or any DAW
Run them with:
cargo run -p minilogue-xd --example berlin_school
Workspace structure
crates/
minilogue-xd/ — Core library (this crate)
minilogue/ — Umbrella crate re-exporting all Minilogue variants
Contributing
Issues and PRs welcome. The MIDI_COVERAGE.md file documents the explicit mapping from
every item in the MIDI implementation document to the Rust type or function that covers it —
a useful starting point for identifying gaps.
License
Licensed under either of:
- MIT license (LICENSE-MIT)
- Apache License, Version 2.0 (LICENSE-APACHE)
at your option.
Not affiliated with Korg Inc.
Dependencies
~0.2–27MB
~333K SLoC