Backend:
- One pw_stream (INPUT, F32) per audio node; for sinks use
stream.capture.sink=true to read the monitor port
- RT process callback computes instantaneous linear peak with no
allocations; stored in std::atomic<float>
- Meter streams are filtered from the registry so they never appear
in the graph or trigger recursive meter creation
- Meter streams are created on first node-ready event, destroyed on
node removal, and cleaned up on engine close
- GET /api/peaks → {node_id: linear_peak} (polled by frontend)
Frontend:
- peaks store polled at 100 ms via setInterval; starts/stops with
initGraph/destroyGraph
- Each node card grows 8 px and shows a 3 px meter bar at the bottom
(green below -12 dB, yellow -12 to -3 dB, red above -3 dB)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>