Skip to content

all3f0r1/onedrop

Repository files navigation

onedrop

Watch the music. Native this time.

A native rewrite of Ryan Geiss's Milkdrop visualizer for Linux, written in Rust. No Wine, no DirectX, no Winamp plugin — a real ELF binary that reads your .milk presets and runs them on Vulkan/wgpu.


Why "one"?

Sister project to oneamp. One audio player, one visualizer — both native, both Rust, same energy. The plan is for them to merge: when onedrop is ready, oneamp's visualization window hosts it behind a feature gate.

What it's trying to be

Milkdrop on Linux. Same per-vertex warp math, same .milk preset format, same shader contract — running on a modern GPU stack (wgpu 29 → Vulkan, Metal, DX12, GL) with no compatibility shim. And because we're rewriting a 25-year-old engine in 2026, we may as well do it in Rust so the next 25 years are someone else's problem.

Why this exists at all

Milkdrop is, to this day, one of the best music visualizers ever shipped. It was tied to Winamp on Windows, written against DirectX 9, and the ecosystem moved on. The Linux options — projectM, Kodi visualizer plugins, MPV with libplacebo — exist, but none of them gives you the feel of running stock Geiss presets the way they were meant to be seen.

projectM is the closest, and it's a serious project. But it's C++, it's been through a few API rewrites, the .milk → GLSL translation has gaps, and it doesn't always feel like 2026 hardware running 2008 art. So this is the ground-up Rust take, with the explicit goal of MilkDrop 2.0d (Geiss, 2008) feature parity, Linux first.

Why MD2 and not MD3? MD 2.0d is the last Geiss-stamped release, and the ecosystem of presets is overwhelmingly MD2-shaped. MD3 is a community fork with added niceties (HardCut, more blend patterns, etc.); we'll backport from it when cheap, but it's not the spec target.

What's in the box

This is v0.10.0. The foundation just landed; the visible visuals are still mostly black. Be warned.

  • .milk parser — line-based preset parser (header, parameters, per-frame and per-pixel equations, custom waves and shapes, embedded warp and composite shader bodies).
  • Expression evaluatorevalexpr 13 backend, ~30 math functions (sin/cos/tan/atan2/sqrt/pow/exp/log/clamp/lerp/...), milkif() for legacy if-as-function calls, q1–q32 user variables, custom variables auto-init.
  • Per-vertex warp pass — the MilkDrop primitive: a 32×24 mesh, CPU-side per-vertex equation evaluation, MD2 warp UV formula (zoom-log → rotation → anisotropic stretch → translation → optional sinusoidal warp), GPU sampling of the previous frame with decay. This is what just shipped in v0.10.0.
  • GPU pipeline — wgpu 29 → Vulkan/Metal/DX12/GL. Headless-friendly via lavapipe (CI tested on Linux/macOS/Windows).
  • Beat detection — six auto-preset-change modes triggered on bass/treble peaks, configurable thresholds, F8 to cycle. (Backported from MD3's HardCut feature; not on the MD2 spec path but trivial to keep.)
  • Audio capturecpal (optional via the audio-input feature) for system input. FFT analyzer scaffolded.
  • CLIinfo / validate / render / list subcommands for .milk files.
  • Workspace — 9 crates, edition 2024, Rust 1.90, 175 tests passing in CI, clippy -D warnings clean.

What you cannot do yet — but is queued in objectives_to_reach.md:

  • Apply the preset's own warp / composite HLSL shaders (they're parsed and stored, but not yet translated to WGSL).
  • Draw waveforms or custom shapes on the canvas. With nothing seeding the feedback loop, the warp pass currently feeds black on black.
  • Motion vectors, borders, gamma, video echo, brighten / darken / solarize / invert, sprites, text overlays, blur pyramid, procedural noise textures, custom texture loading.
  • Render frames to PNG / MP4 from the CLI.
  • Wayland layer-shell desktop mode, fullscreen integration with PipeWire monitor sources.

What's coming

In rough order of priority:

  1. Waveform rendering — the 8 wave_modes, dots/thick/additive — gives the feedback loop something to chew on.
  2. HLSL → WGSL translator — the preset's own warp and composite shaders, via naga's HLSL frontend.
  3. Custom waves and shapes — 4 of each per preset, up to 1024 instances per shape.
  4. Composite filters — gamma, video echo, brighten / darken / solarize / invert, darken_center.
  5. Blur pyramid (GetBlur1/2/3), procedural noise (noise_lq/mq/hq, noisevol_*), user texture loading.
  6. Motion vectors, borders.
  7. Sprites and text overlays (compatible with MILK_IMG.INI / MILK_MSG.INI).
  8. Linux native packaging.deb, AppImage, Flatpak.
  9. oneamp integration — feature-gated drop-in inside oneamp's visualization window.

The full 25-section roadmap with status, current state, and per-item plans lives in objectives_to_reach.md. Per-version detail in CHANGELOG.md.

What this is not

A fork of projectM. A Winamp plugin. A Windows app. A general-purpose shader playground. A media player — see oneamp for that side of the story.

Install

There are no binary releases yet. Build from source.

Build from source

Tested on Debian/Ubuntu, Fedora, and Arch with Rust 1.90.

sudo apt install build-essential pkg-config \
                 libasound2-dev libudev-dev \
                 libxkbcommon-dev libwayland-dev \
                 mesa-vulkan-drivers libvulkan1

git clone https://github.com/all3f0r1/onedrop
cd onedrop
cargo build --release -p onedrop-gui
./target/release/onedrop-gui

For the CLI:

cargo build --release -p onedrop-cli
./target/release/onedrop info path/to/preset.milk

Hotkeys

What works in the GUI today.

Key Action
/ N Next preset
/ P Previous preset
R Reset engine state
F8 Cycle beat-detection mode (Off → HardCut1–6)
Esc / Q Quit

The full Milkdrop 2.0d keymap (Space, H, M, T, Y##, K##, [/], {/}, </>, o/O, I/i, etc.) is queued — see objectives_to_reach.md §18.

Architecture

Workspace of 9 crates:

Crate Role
onedrop-parser .milk file parsing
onedrop-eval Expression evaluation (evalexpr + ~30 math fns)
onedrop-renderer wgpu 29 GPU pipeline (warp mesh, warp pipeline, composite)
onedrop-engine Audio analysis, beat detection, per-vertex warp evaluation, frame loop
onedrop-cli clap-based CLI (info / validate / render / list)
onedrop-gui winit + wgpu app
onedrop-hlsl HLSL → WGSL translation (rudimentary; naga migration queued)
onedrop-codegen Equation → WGSL transpilation, shader caching
tools Internal CLI helpers (preset compatibility tester)

Per-frame pipeline today:

  1. Capture audio (cpal or demo sine) → bass/mid/treb.
  2. Run preset per-frame equations on the evaluator.
  3. Warp pass: for every mesh vertex, clone the evaluator context, run per-vertex equations, apply the MD2 warp formula, upload the resulting UVs to the GPU. The fragment shader samples prev_main at the warped UV, multiplies by decay, writes to current_main.
  4. Copy current_mainprev_main for next frame's feedback.
  5. Blit current_main to the swapchain.

Steps 3 and 4 are the foundation of every Milkdrop preset's motion. The waveform draw, the user composite shader, and post-process filters are the next milestones.

Status

Pre-1.0. The per-vertex warp pass is the first frame-shaped result; everything else listed in objectives_to_reach.md is queued. CI runs on Linux / macOS / Windows with lavapipe headless Vulkan; 175 tests passing, clippy -D warnings clean.

To track or contribute: objectives_to_reach.md for the roadmap, CHANGELOG.md for per-version detail, CONTRIBUTING.md for how to PR.

License

MIT. See LICENSE.

Credits

  • Ryan Geiss — Milkdrop, MilkDrop 2.0d. The reference. The whole reason this project exists.
  • The MilkDrop3 community fork for the HardCut beat-detection modes we backported as a bonus.
  • The projectM team for two decades of cross-platform Milkdrop, even when it hurt.
  • The Rust GPU stack — wgpu, naga, winit, cpal, evalexpr, glam, image — without whom this would still be a pile of HLSL on someone's old hard drive.
  • oneamp for the sister-project blueprint and the Linux-first energy.

About

A modern, pure-Rust reimplementation of the Milkdrop music visualizer

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors