XMrs — SoundTracker file format library
A no_std-friendly Rust library to read, edit and serialize SoundTracker
data — with pleasure.
Because "Representation is the Essence of Programming".
Supported formats
Historical module files — imported into xmrs's in-memory Module model:
| Format | Description | Feature |
|---|---|---|
| MOD | Amiga ProTracker / Soundtracker family | import_mod |
| XM | Fast Tracker II | import_xm |
| S3M | Scream Tracker 3 | import_s3m |
| IT | Impulse Tracker (incl. OpenMPT extras) | import_it |
| XI | Fast Tracker II instrument file | import_xm |
| SID | Commodore 64 / MOS6581 (WIP) | import_sid |
The umbrella feature import enables all of them at once (and is on by
default together with std).
The Module model
xmrs exposes one editor-friendly data model, regardless of what was loaded:
Module ─┬─ Instrument ─┬─ InstrDefault ─┬─ Sample (with loop & sustain-loop)
│ │ ├─ Envelope (volume / panning / pitch)
│ │ ├─ Vibrato
│ │ └─ InstrMidi
│ ├─ InstrEkn (Euclidean-rhythm instrument)
│ ├─ InstrMidi (MIDI instrument)
│ ├─ InstrOpl (Yamaha OPL)
│ ├─ InstrSid (MOS6581 SID voice)
│ └─ InstrRobSid ── InstrSid (Rob Hubbard-style)
└─ Pattern ─ Row ─ TrackUnit ─┬─ TrackEffect
└─ GlobalEffect
Two companion fields on Module describe where the data came from and
how it should play back:
ModuleFormat— purely metadata (Xm,S3m,It,Mod,Unknown). Useful for the UI and for export.PlaybackQuirks— orthogonal switches for each historical replay quirk (FT2 pitch-slide overflow, S3M period clamp, arpeggio LUT, pattern-loop resume, tremor state, …). Importers populate them to match the source format; modules authored from scratch default to a clean, quirk-free playback.
This separation lets an editor compose any subset of historical behaviours without having to lie about which tracker the module "came from".
Loading a file
use *;
let bytes = read?;
// Auto-detect: tries XM → S3M → IT → MOD.
let module = load?;
// Or target a specific format:
let module = load_xm?;
println!;
Format-specific constructors are also available: Module::load_mod,
load_xm, load_s3m, load_it. SID is imported via its own entry
point, xmrs::import::sid::sid_module::SidModule::load, and is not part
of the auto-detect path.
Serialization
Module derives serde::Serialize / Deserialize, so you can round-trip
it through any serde codec.
Examples
Run from the xmrs crate directory:
# Dump any supported module file:
# Dump an XI (Fast Tracker II instrument) file:
# Exercise the bundled SID parsers (Rob Hubbard tunes):
Cargo features
Defaults: ["std", "import"].
| Feature | Purpose |
|---|---|
std |
Build against std; uses f32's inherent math methods. |
import |
Umbrella: enables every import_* format importer. |
import_mod |
Amiga ProTracker MOD. |
import_xm |
Fast Tracker II XM (and XI instruments). |
import_s3m |
Scream Tracker 3 S3M. |
import_it |
Impulse Tracker IT. |
import_sid |
Commodore 64 SID (bundled Rob Hubbard tunes). |
libm |
Float math via libm (pick one in no_std). |
micromath |
Float math via micromath (pick one in no_std). |
demo |
Pulls in clap, std and import for the CLI examples. |
rand8 / rand16 / rand64 |
Extra xorshift widths (rand32 is always on). |
no_std builds
With std disabled, exactly one math backend is required — the crate
refuses to compile otherwise:
# libm backend:
# micromath backend (smaller, less precise):
Embedded / footprint-sensitive builds
If you're targeting tight flash budgets, don't ship the importers.
Parse modules on a host machine, serialize with
bincode 2.x (alloc feature) —
optionally compressed with
flate2 — and load the resulting
blob on-device. You end up with a much smaller binary that still
manipulates the full Module model.
License
MIT © Sébastien Béchet. See LICENSE.