             info =
                 key: key
                 velocity: message[2]
-                timestamp: midiTime
+                timestamp: clock()
 
             # Split keyboard into particles and LFOs
             if key >= 60

    for p in particles

        # Angle: Global spin, thne positional mapping to key
        theta = spinAngle + (Math.PI / 5) * p.note.key

        # Positioned in polar coordinates, on unit circle
        x = Math.cos theta
        y = Math.sin theta

        # Add influence of LFOs
        for key, note of lfoNotes

            # Down several octaves, to useful LFO frequencies
            transpose = -12 * 5

            # Midi note to frequency
            hz = 440 * Math.pow 2, (note.key - 69 + transpose) / 12

            # Wobble amplitude driven by LFO
            wobbleAmp = Math.sin Math.PI * 2 * now * hz

            # Wobble angle driven by LFO note and particle life
            wobbleAngle = 10.0 * p.life + (Math.PI / 5) * p.note.key

            x += wobbleAmp * Math.cos wobbleAngle
            y += wobbleAmp * Math.sin wobbleAngle

        # Radius: Particles spawn in center, fly outward
        radius = 3.0 * (1 - p.life)
        x *= radius
        y *= radius

        # Use the XZ plane
        p.point = [x, 0, y]

        # One rainbow per octave
        hue = (p.note.key - 60) / 12.0
        p.color = OPC.hsv hue, 0.5, 0.8

        # Intensity mapped to velocity, nonlinear
        p.intensity = Math.pow(p.note.velocity / 100, 5.0) * brightness

        # Falloff gets sharper as the note gets higher
        p.falloff = 20 + (p.note.key - 60) * 20

        p.life -= timeStep / particleLifetime


draw = () ->

    # Time delta calculations
    now = clock()
    timeStep = now - previousNow
    previousNow = now

