wobblemidi v1.0.0
First stable release. wobblemidi humanises programmed drum MIDI by sampling
timing and velocity deviations from real drummer performances — the
Groove MIDI Dataset
(341 rock takes, 114,890 hits, Roland TD-11) — instead of adding random jitter.
Highlights
- Statistical timing & velocity sampled per instrument, grid position,
beat/fill context, and dynamic tier (per-bucket KDE, six-level fallback for
sparse buckets, per-bucket outlier clipping). - One clock for the kit — an AR(1) groove-drift clock (phi calibrated
≈0.37 from the data) correlates timing across the whole kit so it breathes
as a pocket instead of scattering; kick velocity gets its own drift clock
(the one instrument where human velocities measure strongly autocorrelated). - Flam & chord preservation — same-tick hits and close-spaced ornaments
(≤12 ms) move as one rigid unit; seedemo/flam_beat_*.midfor the A/B. - Relative velocity tiering — ghost/accent roles are read from your file's
own velocity structure, so programmed dynamics survive humanisation. - De-biased timing by default — the source drummers' systematic push/drag
is removed (kept as spread, not lean);--pushrestores the authentic lean. - Controls:
--intensity(default 0.35; 0.2–0.5 is the useful range),
--groove-tightness,--section beat|fill,--seed,--timing-only/
--velocity-only,--all-channels. Per-lane intensity and lean amount in
the GUI/API. - GUI —
wobblemidi-gui(pywebview): drag a file in, turn knobs, audition,
export. macOS .app attached below.
Validation, honestly
The engine gates on a harness that scores it against held-out human takes
(GMD's own train/test split) — per-instrument offset distributions
(Wasserstein/KS/σ/mean), within-position velocity spread, adjacent-jump
distributions, contour preservation, lag-1 autocorrelation, cross-instrument
gap tightness — all two-sided against human, so "more robotic than a drummer"
and "sloppier than a drummer" both fail. Then ear-tested.
Two known misses are accepted and documented, not hidden:
- At full intensity, kick/hat/ride velocities carry 2–3× a human's
within-role spread (unimodal excess; masked at the 0.35 default; the next
lever — a velocity analogue of the AR timing clock — is identified). - Snare emits slightly too few exactly-repeated velocities compared with
human ghost runs — structural to continuous KDE sampling, cosmetic.
Engineering
- Deterministic: one seed, three isolated RNG streams; semantics frozen in
wobblemidi_determinism.md. - 26 golden vectors byte-lock the engine across the full parameter surface,
verified on every CI run on Linux + macOS (308 tests total). - This engine is the reference implementation for a planned JUCE/AU Logic
plugin; the port gate is defined inwobblemidi_porting_contract.md.
Assets
wobblemidi-1.0.0-macos-arm64.zip— the GUI as a macOS app
(unsigned: right-click → Open on first launch).wobblemidi-1.0.0-demo-midi.zip— the seeded before/after MIDI pairs; see
demo/README.mdfor what to listen for in each.wobblemidi-1.0.0-py3-none-any.whl/.tar.gz— pip-installable build.
Install
pip install git+https://github.com/JakebGutierrez/wobblemidi(or pip install the attached wheel; add the [gui] extra for the GUI).
Licensed MIT. Profile data derived from the Groove MIDI Dataset, © Google LLC,
CC BY 4.0.