For Visual Artists

← Back to Index


What You Receive

When you connect to this system, you receive a stream of values that describe what the music is doing right now. You do not receive raw audio data, frequency bins, or FFT buffers. You receive meaningful descriptions of the music expressed as simple values.

Here is everything the system sends you:

  story.name            String or null.
                        The name of the current moment:
                        "groove", "escalation", "breakdown", "drop", etc.
                        null when the kick is absent and no story applies.

  story.phase           String.
                        Where we are in this story's lifecycle:
                        "entering", "sustaining", or "transitioning"

  story.duration        Number (bars).
                        How many bars we have been in this story.

  foundation.weight     Float (0.0 – 1.0).
                        How heavy the kick feels.
                        0.0 = barely there. 1.0 = floor-shaking.
                        Updates every frame. Smooth, no jitter.

  foundation.presence   Float (0.0 – 1.0).
                        How clearly the kick cuts through the mix.
                        1.0 = crystal clear. 0.0 = gone.
                        Updates every frame. Smooth, no jitter.

  foundation.sustain    String: "dry", "mid", or "wet".
                        How the kick decays after impact.
                        Changes infrequently (every few bars at most).

  variance.direction    String: "rising", "stable", or "falling".
                        Is the energy around the kick going up,
                        staying the same, or coming down?
                        Changes infrequently (confirmed over 2+ bars).

  variance.magnitude    Float (0.0 – 1.0).
                        How fast or dramatically things are shifting.
                        0.0 = nothing changing. 1.0 = dramatic shift.
                        Updates every frame. Smooth.

That’s it. Nine values. Everything you need to create visuals that respond meaningfully to live techno music.


What You Don’t Need to Know

You do not need to understand any of the following to use this system:

  • What an FFT is or how beat detection works
  • What frequency bins are or what Hz means
  • How Pro DJ Link communicates BPM data
  • What temporal thresholds are or how debouncing works
  • How the kick is isolated from the rest of the signal
  • What spectral brightness or onset density means

All of that is handled by the engineering layer beneath this model. By the time the data reaches you, it has already been analyzed, interpreted, smoothed, and confirmed. You receive meaning, not data.


Two Types of Values

The nine values fall into two categories, and understanding this distinction will help you use them effectively.

Continuous Values (drive smooth visuals)

These update every frame. They move gradually and smoothly. Use them for things that should change fluidly — size, opacity, color intensity, blur, speed.

  foundation.weight       → size, intensity, scale
  foundation.presence     → opacity, sharpness, saturation
  variance.magnitude      → speed, complexity, particle count

These values are your primary visual drivers. They are always available, always smooth, and always responsive to the music.

State Values (drive structural changes)

These change infrequently — every few bars, sometimes every few minutes. When they change, it means something significant has happened in the music. Use them for things that should change discretely — color palette, geometry type, scene selection, transition effects.

  story.name              → which visual scene / palette / mode
  story.phase             → whether to be transitioning between scenes
  foundation.sustain      → the "texture" or "feel" of the visual
  variance.direction      → whether visuals should be intensifying, steady, or calming

Example Mappings

Basic: Weight Drives Everything

The simplest possible mapping. Weight alone can create responsive, meaningful visuals.

  // The kick IS the visual
  shape.size       = foundation.weight * maxSize
  shape.brightness = foundation.weight * maxBrightness
  shape.speed      = foundation.weight * maxSpeed

  // When the kick is heavy, everything is big and bright.
  // When the kick is light, everything is small and dim.
  // When the kick disappears, presence drops to 0 and
  // you can fade everything out.

Intermediate: Weight + Presence + Story

Adding Presence and Story creates more nuanced, structural responses.

  // Weight drives size
  shape.size = foundation.weight * maxSize

  // Presence drives clarity
  shape.opacity   = foundation.presence
  shape.blur      = (1.0 - foundation.presence) * maxBlur
  shape.sharpness = foundation.presence

  // Story drives the scene
  if (story.name == "groove")      { palette = warm;  geometry = solid }
  if (story.name == "escalation")  { palette = hot;   geometry = expanding }
  if (story.name == "breakdown")   { palette = cool;  geometry = dissolving }
  if (story.name == "drop")        { palette = flash; geometry = explosive }

  // Story phase drives transitions
  if (story.phase == "transitioning") {
    crossfade(currentScene, nextScene, transitionSpeed)
  }

Advanced: Full Model

Using all nine values for maximum expressiveness.

  // Foundation drives the core visual
  shape.size       = foundation.weight * maxSize
  shape.opacity    = foundation.presence
  shape.blur       = (1.0 - foundation.presence) * maxBlur

  // Sustain drives visual texture
  if (foundation.sustain == "dry") {
    shape.edges    = sharp
    shape.decay    = instant       // visuals snap on/off with the beat
    shape.style    = geometric
  }
  if (foundation.sustain == "mid") {
    shape.edges    = smooth
    shape.decay    = natural       // visuals fade naturally between beats
    shape.style    = organic
  }
  if (foundation.sustain == "wet") {
    shape.edges    = blurred
    shape.decay    = trailing      // visuals linger, blend, overlap
    shape.style    = atmospheric
  }

  // Variance drives energy and movement
  if (variance.direction == "rising") {
    movement.speed     = baseSpeed * (1.0 + variance.magnitude)
    particles.count    = baseCount * (1.0 + variance.magnitude * 2)
    color.temperature  = shifting_warmer
  }
  if (variance.direction == "stable") {
    movement.speed     = baseSpeed
    particles.count    = baseCount
    color.temperature  = neutral
  }
  if (variance.direction == "falling") {
    movement.speed     = baseSpeed * (1.0 - variance.magnitude * 0.5)
    particles.count    = baseCount * (1.0 - variance.magnitude)
    color.temperature  = shifting_cooler
  }

  // Story drives the scene and transitions
  scene.current = mapStoryToScene(story.name)
  if (story.phase == "transitioning") {
    beginSceneTransition()
  }

Handling Null Story

When story.name is null, the kick is absent and the model has nothing to say about the music. This happens during breakdowns, between tracks, or during ambient sections.

Your visual system needs a strategy for this. Some options:

  Option 1: Fade to minimal state
    When story.name becomes null, gradually reduce all visual output
    to a dim, ambient baseline. Resume when story returns.

  Option 2: Hold the last state
    Freeze the visual at its current state when story becomes null.
    Let it sit there as a static image until the music returns.

  Option 3: Freeform mode
    When story.name is null, switch to a generative/autonomous visual
    mode that doesn't depend on the kick. Run procedural animations,
    slow drifts, ambient patterns. Return to music-driven mode when
    story resumes.

  Option 4: Use presence as the guide
    Even when story is null, foundation.presence is still updating.
    If presence is 0.0, the kick is truly gone. If presence is 0.3,
    there might be ghost kicks or residual energy. Use this continuous
    value to scale your ambient state.

Tips

Start with weight. Before you map anything else, get weight driving a single visual parameter (size or brightness). If that feels good and responsive, add more mappings. If it doesn’t, no amount of additional complexity will fix it.

Don’t map everything to everything. Nine inputs mapped to twenty visual parameters creates visual noise. Pick 3-4 strong mappings and let the rest be implicit or secondary.

Sustain is your texture knob. DRY sustain should make your visuals feel mechanical and precise. WET sustain should make them feel dreamy and flowing. MID is the baseline. If your visuals feel the same regardless of sustain, you’re missing an opportunity.

Story phase is your transition cue. When story.phase changes to “transitioning,” something is about to change. Use this to begin visual transitions before the new story arrives. The audience will feel the visual shift anticipating the musical shift — which is exactly how good VJ work feels.

Variance magnitude is your “something is happening” signal. Even without looking at direction, if magnitude is high, the music is in motion. If magnitude is low, it’s locked in. Use this for particle counts, movement speed, visual complexity — anything that should increase when the music is active.


  • Story — what story names mean and how they work
  • Weight — deep dive on the primary visual driver
  • Presence — deep dive on kick clarity
  • Sustain — deep dive on kick decay character
  • Variance — deep dive on energy direction and magnitude

← Back to Index