Data Layer (react_ui/src/data/)
State management, engine↔JS bridge, and real-time metering.
Files
| File | Purpose |
|---|---|
bridge.ts | Engine↔JS communication layer. StateStorage for Zustand persistence (via invoke() from @/sync/transports/promiseHandler), addStateListener for engine events. |
meters.ts | Real-time metering: useMeterStore (Zustand), raw rtBuffer, ballistic smoothing engine, subscribeRtBuffer API. |
store.ts | Primary Zustand stores (useTransportStore, useMixerStore, etc.) with engine persistence. |
plugins.ts | Plugin scanning and management state. |
sliderDrag.ts | Shared slider drag utilities. |
inlineGenFlag.ts | Feature flag for inline AI generation (Option+click-drag). |
slices/collab.ts | Collaboration state slice: connected users, room info, cursor positions. |
slices/inlineGenerate.ts | Inline generation state slice: drag region, progress, results. |
slices/customEditors.ts | Custom editor panel state: active stock plugin UI, editor visibility. |
slices/scriptFxEditors.ts | ScriptFX editor state: open editors, script content, compilation status. |
Real-Time Metering Pipeline
Three-Layer Architecture
-
rtBuffer— Raw mutable object, written by the engine event handler. No subscriptions, no notifications. Just a data landing zone. -
displayBuffer— Smoothed values computed by therequestAnimationFrameloop. Applies ballistic smoothing so meters look fluid even with 30Hz data input. Subscribers receive this. -
useMeterStore(Zustand) — Throttled to ~10Hz for the few React components that still use reactive selectors. Most components usesubscribeRtBufferinstead.
Ballistic Smoothing Constants
| Element | Release Factor | Effective Decay | Rationale |
|---|---|---|---|
| Level meters | 0.88 | ~300ms | Matches professional PPM meter ballistics |
| Spectrum bars | 0.82 | ~200ms | Slightly faster for responsive spectrum display |
| Stereo/phase | 0.85 | ~250ms | Bidirectional smoothing (not attack/release) |
| CPU | 0.95 | ~600ms | Slow-moving data, avoid visual noise |
API
Rendering Best Practices
All meter components use direct DOM manipulation viasubscribeRtBuffer (no React re-renders):
| ✅ Do | ❌ Don’t |
|---|---|
style.transform = 'scaleY(...)' | style.height = '...' |
style.transform = 'scaleX(...)' | style.width = '...' |
style.transform = 'translateX(...)' | style.left = '...' |
will-change: transform | CSS transition-* on high-freq elements |
subscribeRtBuffer() | useMeterStore(selector) for meters |
height/width/left trigger browser layout recalculation (~0.5ms per property). transform is GPU-composited — the browser sends a matrix to the GPU with no layout cost.