> ## Documentation Index
> Fetch the complete documentation index at: https://songbird.studiocollective.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Layer (`react_ui/src/data/`)

# 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

```
Engine (30Hz) → bridge.ts  →  rtBuffer (mutable)  →  rAF ballistic smoothing  →  displayBuffer  →  DOM
                  (no log)       (raw data)              (60Hz, instant attack,      (smoothed)       (GPU transforms)
                                                          ~300ms release decay)
```

### Three-Layer Architecture

1. **`rtBuffer`** — Raw mutable object, written by the engine event handler. No subscriptions, no notifications. Just a data landing zone.

2. **`displayBuffer`** — Smoothed values computed by the `requestAnimationFrame` loop. Applies ballistic smoothing so meters look fluid even with 30Hz data input. Subscribers receive this.

3. **`useMeterStore`** (Zustand) — Throttled to \~10Hz for the few React components that still use reactive selectors. Most components use `subscribeRtBuffer` instead.

### 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            |

Attack is always **instant** — when the new value exceeds the current smoothed value, it snaps immediately.

### API

```typescript theme={null}
// Subscribe to smoothed display-rate data (~60Hz via rAF)
const unsub = subscribeRtBuffer((buf) => {
  // Direct DOM updates here — no React re-renders
  el.style.transform = `scaleY(${buf.master.left / 100})`;
});

// Get the raw (unsmoothed) latest data
const raw = getRtBuffer();
```

### Rendering Best Practices

All meter components use **direct DOM manipulation** via `subscribeRtBuffer` (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     |

**Why transforms?** `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.

### Event Flow

```
Engine PlaybackInfo (30Hz timer)
  → ctx.send("meters:rt_frame", json)
  → bridge.ts addStateListener("meters:rt_frame", ...)
      (pushLog skipped for rt_frame — would saturate 200-entry buffer)
  → JSON.parse → write to rtBuffer
  → markNewData() — ensures rAF loop is running
  → rAF loop applies ballistic smoothing → displayBuffer
  → subscribeRtBuffer callbacks → direct DOM updates
```
