The Minilogue XD exposes a remarkably deep MIDI surface: 50+ CC parameters,
29 NRPN parameters, a 1024-byte program blob containing the full synth state,
a 16-step sequencer with 4-slot motion sequences, sub-cent tuning tables for
all 128 notes, and a complete user module management protocol for logue SDK units.
This library covers all of it — with typed Rust APIs, correct 10-bit encoding,
the Korg 7-bit SysEx codec, and file format support for .mnlgxdprog,
.mnlgxdlib, and .mnlgxdunit archives.
Additionally, performances can be exported as Standard MIDI Files
(.mid) — complete with patch setup CCs, parameter automation,
and note data — ready for notation software like Sibelius or any DAW.
The dream: treat the XD desktop module as a voice in an imaginary MIDI-based
Eurorack system (or not so imaginary...),
with every parameter reachable from Rust in real time.
Working with the physical synth, we are limited to our two hands
(and foot pedals); working with software, we become thousand-armed
Chenrezig musicians.
# 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.
# no_std / file-only build
minilogue-xd = { version = "0.1", default-features = false, features = ["file-formats"] }
use minilogue_xd::{ controller::RealtimeController, device, message::{U4, U7}, param::enums::{VcoWave, LfoMode, EgTarget, MicroTuning}, transport::MidirOutput, }; fn main() -> minilogue_xd::Result<()> { let port = device::find_output_port()? .expect("Minilogue XD not found"); let output = MidirOutput::connect(&port)?; let mut xd = RealtimeController::new(output, U4::new(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(U7::new(60)?, U7::new(100)?)?; // middle C, velocity 100 Ok(()) }
use minilogue_xd::{ builder::patch::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(true, DelaySubType::Tape, 0.4, 0.6, 0.3) .build(); // Send it to the edit buffer over SysEx let mut tx = SysexTransaction::new(&mut output, &mut input, channel); tx.send_current_program(&patch)?; // Load a .mnlgxdlib file from disk use minilogue_xd::sysex::program::file::read_lib_file; let file = std::fs::File::open("factory.mnlgxdlib")?; let patches = read_lib_file(file)?; println!("{} patches loaded", patches.len());
Runnable demos in the examples/ directory, verified on real hardware: