VizLab
VizLab — Claude Context
Audio-reactive visualization design workbench. Loads Touchstone recipes, runs them through a RecipeEngine with mock signal input, polls snapshot data, and renders visual arrangements on a SwiftUI Canvas.
Dependencies
Touchstone + Horatio only (same as Workbench). No Ariel, Enobarbus, camera, or Bluetooth.
Data Flow
Recipe JSON → RecipeEngine (real audio processing)
↓ (30 Hz snapshot polling)
SnapshotData (per-node FDSPSnapshot)
↓
VisualState (flat [String: Float] dictionary)
↓ (ParameterMappings with curves/ranges)
ArrangementRenderer (TimelineView + Canvas, 60 fps)
Signal Chain
SignalGenerator → Input Level → RecipeEngine L/R
→ Auto-Gain → BrickwallLimiter L/R
→ [Mute gate] → Waveform ring buffer → Output
Architecture
Audio
| File |
Role |
Audio/VizLabAudioEngine.swift |
Effects-mode-only engine: SignalGenerator → RecipeEngine → limiter. Snapshot access via readNodeSnapshot(). outputMuted flag for silent processing. |
Audio/SignalGenerator.swift |
Phase-accumulator signal generation (13 types, no live/sample) |
Audio/SignalType.swift |
Signal type enum (no live input) |
Models
| File |
Role |
Models/VizLabState.swift |
@Observable central state: recipe loading, snapshot polling (30 Hz), visual state rebuild, arrangement management, manual overrides |
Models/VisualRecipe.swift |
Codable: arrangement type + parameter mappings + color config |
Models/ParameterMapping.swift |
Source → output with curve/range, reuses Touchstone ModulationCurve |
Models/ArrangementType.swift |
Enum: plasmaNebula, dotSwarm, eqBars, waveformScope, ringVisualizer, lissajous, gridWarp |
Models/VisualDocument.swift |
FileDocument for JSON export/import |
Models/SnapshotReader.swift |
Field extraction from FDSPSnapshot (ported from Workbench) |
Views
| File |
Role |
ContentView.swift |
NavigationSplitView: sidebar (recipes + arrangements) + detail (canvas + inspector) |
Views/CanvasView.swift |
TimelineView + Canvas at 60 fps, dispatches to active Arrangement |
Views/ArrangementPicker.swift |
Browse/select arrangement type |
Views/MappingEditor.swift |
Connect snapshot fields → visual params |
Views/MockControlsView.swift |
Signal type + frequency + manual override sliders |
Arrangements
| File |
Role |
Views/Arrangements/Arrangement.swift |
Protocol: update(dt:visualState:), draw(context:size:time:visualState:), parameterDefinitions |
Views/Arrangements/PlasmaArrangement.swift |
Particle system with spiral attractor (ported from Hecate PlasmaFieldView) |
Arrangement Protocol
protocol Arrangement: AnyObject {
func update(dt: Double, visualState: [String: Float])
func draw(context: inout GraphicsContext, size: CGSize, time: Double, visualState: [String: Float])
static var parameterDefinitions: [ArrangementParamDef] { get }
}
Class-type for mutable frame-to-frame state (particle pools, phase accumulators).
Visual State
Flat [String: Float] dictionary. Keys:
- "rms" — computed from waveform samples
- "nodeId.fieldName" — extracted from FDSPSnapshot per node
- Mapped parameter names from VisualRecipe mappings
- Manual overrides take precedence
Rules
- No Ariel or Enobarbus imports.
@ObservationIgnored + _rt prefix for all audio-thread state.
- BrickwallLimiter always on, never bypassable.
- Snapshot polling on main thread (30 Hz timer), Canvas draw at 60 fps.
- Arrangements are reference types (class) — hold mutable state.