feat: real-time dB level meters per node
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>
This commit is contained in:
@@ -302,6 +302,21 @@ void WebServer::setupRoutes() {
|
||||
res.set_header("Access-Control-Allow-Origin", "*");
|
||||
});
|
||||
|
||||
// Level meters: GET /api/peaks → {"<node_id>": <linear_peak_0_1>, ...}
|
||||
m_http.Get("/api/peaks", [this](const httplib::Request &, httplib::Response &res) {
|
||||
auto peaks = m_engine.getPeaks();
|
||||
std::string json = "{";
|
||||
bool first = true;
|
||||
for (auto &[id, peak] : peaks) {
|
||||
if (!first) json += ",";
|
||||
json += "\"" + std::to_string(id) + "\":" + std::to_string(peak);
|
||||
first = false;
|
||||
}
|
||||
json += "}";
|
||||
res.set_content(json, "application/json");
|
||||
res.set_header("Access-Control-Allow-Origin", "*");
|
||||
});
|
||||
|
||||
// REST API: POST /api/connect
|
||||
m_http.Post("/api/connect", [this](const httplib::Request &req, httplib::Response &res) {
|
||||
uint32_t out_id = 0, in_id = 0;
|
||||
|
||||
Reference in New Issue
Block a user