Milkdrop is a Winamp music visualization plugin from back in the day (ca 2001). It had a really active community of folks releasing thousands and thousands of “presets” and afaik there isn’t anything else today with that kind of scene.

Resources

Ryan Geiss homepage
https://www.geisswerks.com/about_milkdrop.html

https://github.com/projectM-visualizer/projectm
open source reimplementation of milkdrop

https://butterchurnviz.com/
Milkdrop in browser

NestDrop VJ environment
https://nestimmersion.ca/nestdrop.php

MilkDrop2077 : a free and open-source presets masher and randomizer for MilkDrop
https://forums.winamp.com/forum/visualizations/milkdrop/milkdrop-presets/315458

See also:

Preset packs

https://www.geisswerks.com/about_milkdrop.html
Ryan Geiss favorites

bltc pack
https://forums.winamp.com/forum/visualizations/milkdrop/milkdrop-presets/173840-bltc-1-4

NestDrop cream of the crop
https://www.patreon.com/posts/pack-nestdrop-91682111

Archive.org MilkDrop Preset Collection
https://archive.org/details/milkdrops

How it works

“geiss” is an earlier proto-milkdrop

https://www.geisswerks.com/geiss/secrets.html

  1. Draw some audio waveform into an image.
  2. Warp the image.

The first step is pretty cheap; the second step is the computationally expensive one.

Running Milkdrop

I installed projectm with homebrew but found that keyboard shortcuts didn’t work. It may have been compiled with them disabled?

Instead, I downloaded and ran the latest standalone projectM SDL frontend application precompiled for Mac OS following instructions.

Note: the homebrew and standalone versions came with different preset packs.

Preset authoring

MILKDROP preset authoring guide
https://www.geisswerks.com/milkdrop/milkdrop_preset_authoring.html
scripting reference

projectM Milkdrop Preset Expression Syntax
https://github.com/projectM-visualizer/projectm-eval/blob/master/docs/Expression-Syntax.md

Beginners Guide to MilkDrop Preset Writing by Rovastar and Krash
https://web.archive.org/web/20130523223615/http://www.milkdrop.co.uk/guide.htm
tutorial

Getting started

I moved the presets directory to presets_bak and made a new presets directory with a file hello.milk. Then I followed instructions in the milkdrop.co.uk tutorial to create a blank preset with sensible defaults:

So the initial advice is simple create a blank preset with no zoom, no rot, no warp, no colours, etc. And here is one created for you.

[preset00]
fRating=3.000000
fGammaAdj=1.000000
fDecay=0.925000
...

Concepts

  • per-frame vs. per-vertex equations
  • wave_mode
  • decay
  • variables
    • zoom, rot, warp, cx/cy, dx/dy, sx/sy
    • time, frame
    • bass, mid, treb, bass_att, mid_att, treb_att
  • per-vertex variables
    • rad, ang, x, y

Custom shapes and waves

TODO

Shaders

TODO

Milkdrop uses Direct3D HLSL

warp shader, composite shader

https://www.geisswerks.com/milkdrop/milkdrop_preset_authoring.html#3f

projectM glsl
https://spiegelmock.com/2018/07/29/projectm-opengl-and-shader-modernization/

Beat detection

milkdrop.co.uk tutorial Section 9.5 Tutorial 4 - Shift

The fourth tutorial covers the preset “Shift”. This preset introduces a commonly used method of beat detection, which can be easily transported across into other presets.

IF bass_att is greater than bass_thresh  
THEN set bass_thresh to 2  
ELSE do (stuff)  
ENDIF

Now, we need to focus on what that (stuff) part does. I’ve reproduced it here:
(bass_thresh - 1.3)*0.96 + 1.3

A plain english version of the equation is:
“Take 96% of the difference between bass_thresh and 1.3, and add it to 1.3”
This generates an exponential/log curve

This means that the bass_thresh value will start at a point (in this case, 2), and drop. The value will drop relatively quickly at first, but will slow down; eventually getting so close to 1.3 that it IS 1.3.

So what happens then? Well, at some point, the bass_att (which is the percentage of the bass in this frame relative to the last frame) will be above our threshold, and the threshold will be set to 2 again. Incidentally, this is the same way that MilkDrop detects beats for its “Hard Cuts”.

IF bass_thresh = 2 (i.e. we have just detected a beat) 
THEN set dx_residual to 0.016*sin(time*7) (which is essentially a random number between -0.016 and 0.016) 
ELSE keep dx_residual the same (multiplying itself by 1) 
ENDIF 

The dy_residual equation works in the same way. The three lines of code are therefore generating two random numbers between -0.016 and 0.016 every time we detect a beat.

See also:

improved beat detection
https://forums.winamp.com/forum/visualizations/milkdrop/milkdrop-development/4622543-the-real-milkdrop-s-perfect-beat-detection?p=4622699#post4622699