Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
live_dsp_telemetry.hpp
Go to the documentation of this file.
1#pragma once
2
24
25#include <atomic>
26#include <chrono>
27#include <cstdint>
28#include <span>
29#include <string_view>
30#include <vector>
31
32namespace pulp::audio {
33
46
47const char* to_string(LiveDspNodeKind kind) noexcept;
48
52 std::uint64_t node_id = 0;
54 std::uint32_t input_ports = 0;
55 std::uint32_t output_ports = 0;
56 char name[64] = {};
57
58 void set_name(std::string_view value) noexcept;
59};
60
63 std::uint32_t ring_blocks = 256;
65 std::uint32_t percentile_window_blocks = 256;
68 float graph_overload_load = 1.0f;
70};
71
73 std::uint64_t node = 0, root = 0, epoch = 0, expected_sequence = 0;
74 std::uint64_t errors = 0;
75 std::int64_t first_error_position = 0, latest_origin = 0;
76 std::uint8_t first_error = 0;
77};
78
81 std::uint64_t node_id = 0;
83 char name[64] = {};
84
85 std::uint64_t sample_count = 0;
86 std::int64_t last_elapsed_ns = 0;
87 std::int64_t min_elapsed_ns = 0;
88 std::int64_t max_elapsed_ns = 0;
89 std::int64_t mean_elapsed_ns = 0;
90 std::int64_t p50_elapsed_ns = 0;
91 std::int64_t p95_elapsed_ns = 0;
92 std::int64_t p99_elapsed_ns = 0;
93 std::int64_t jitter_ns = 0;
95 std::uint64_t over_budget_attributions = 0;
96};
97
100 bool available = false;
101 bool enabled = false;
102 std::uint64_t sequence_number = 0;
103
104 std::uint32_t node_count = 0;
105 std::uint64_t blocks_written = 0;
106 std::uint64_t blocks_drained = 0;
107 std::uint64_t blocks_dropped = 0;
108 std::uint64_t graph_over_budget_blocks = 0;
109
110 double sample_rate = 0.0;
111 std::uint32_t last_frame_count = 0;
112 std::int64_t last_available_ns = 0;
113 std::int64_t last_graph_elapsed_ns = 0;
114 float last_graph_load = 0.0f;
115
116 std::vector<LiveDspNodeSummary> nodes;
117 std::vector<LiveDspSpectralDiagnostic> spectral;
118 std::uint64_t observed_block = 0;
119 std::uint64_t observed_drops = 0;
120 std::uint64_t age_blocks = 0;
121};
122
124
129public:
130 LiveDspTelemetryNodeScope() noexcept = default;
132 std::uint32_t node_slot) noexcept;
134
139
140private:
141 LiveDspTelemetryStore* store_ = nullptr;
142 std::uint32_t ring_slot_ = 0;
143 std::uint32_t node_slot_ = 0;
144 std::chrono::steady_clock::time_point start_{};
145};
146
150public:
151 LiveDspTelemetryBlockWriter() noexcept = default;
153 std::uint32_t frame_count, double sample_rate) noexcept;
154
160
161 bool active() const noexcept { return store_ != nullptr; }
162
165 LiveDspTelemetryNodeScope node(std::uint32_t node_slot) noexcept;
166
169 void finish() noexcept;
170
171private:
172 LiveDspTelemetryStore* store_ = nullptr;
173 std::uint32_t ring_slot_ = 0;
174 std::chrono::steady_clock::time_point start_{};
175};
176
179public:
181
185 bool prepare(const LiveDspTelemetryConfig& config, std::span<const LiveDspNodeInfo> nodes);
186
187 void set_enabled(bool enabled) noexcept { enabled_.store(enabled, std::memory_order_relaxed); }
188 bool enabled() const noexcept { return enabled_.load(std::memory_order_relaxed); }
189
190 std::uint32_t node_count() const noexcept { return node_count_; }
191 bool prepared() const noexcept { return node_count_ != 0; }
192
195 LiveDspTelemetryBlockWriter begin_block(std::uint32_t frame_count, double sample_rate) noexcept;
196
204 void inject_block(std::span<const std::int64_t> node_ns, std::int64_t graph_elapsed_ns,
205 std::uint32_t frame_count, double sample_rate,
206 std::span<const LiveDspSpectralDiagnostic> spectral = {}) noexcept;
207 std::span<LiveDspSpectralDiagnostic> spectral_scratch() noexcept {
208 return spectral_scratch_;
209 }
210
215 std::int64_t* external_record_scratch() noexcept {
216 return record_scratch_.empty() ? nullptr : record_scratch_.data();
217 }
218
221 void drain() noexcept;
222
224 const LiveDspTelemetrySnapshot& latest() const noexcept { return snapshot_; }
225
226 std::uint64_t blocks_written() const noexcept { return write_index_.load(std::memory_order_acquire); }
227 std::uint64_t blocks_dropped() const noexcept { return dropped_.load(std::memory_order_relaxed); }
228
229private:
232
233 // Audio-thread write helpers (called by the writer/scope friends).
234 void write_node_elapsed(std::uint32_t ring_slot, std::uint32_t node_slot,
235 std::int64_t elapsed_ns) noexcept;
236 void publish_block(std::uint32_t ring_slot, std::int64_t graph_elapsed_ns) noexcept;
237
238 struct BlockHeader {
239 std::uint64_t observed_block = 0, observed_drops = 0;
240 std::uint32_t frame_count = 0;
241 double sample_rate = 0.0;
242 std::int64_t available_ns = 0;
243 std::int64_t graph_elapsed_ns = 0;
244 };
245
246 std::uint32_t node_count_ = 0;
247 std::uint32_t ring_blocks_ = 0;
248 std::uint32_t window_blocks_ = 0;
249 float graph_overload_load_ = 1.0f;
250
251 std::atomic<bool> enabled_{false};
252
253 // SPSC ring: producer = audio thread, consumer = drain(). write_/read_index_
254 // are monotonic; slot = index % ring_blocks_.
255 std::atomic<std::uint64_t> write_index_{0};
256 std::atomic<std::uint64_t> read_index_{0};
257 std::atomic<std::uint64_t> dropped_{0};
258 std::atomic<std::uint64_t> observed_blocks_{0};
259
260 std::vector<BlockHeader> ring_headers_; // [ring_blocks_]
261 std::vector<std::int64_t> ring_node_ns_; // [ring_blocks_ * node_count_]
262 std::vector<LiveDspSpectralDiagnostic> ring_spectral_, spectral_scratch_;
263
264 // Drain-side rolling windows (one ring of the last window_blocks_ samples per node).
265 std::vector<std::int64_t> window_ns_; // [node_count_ * window_blocks_]
266 std::vector<std::uint32_t> window_pos_; // [node_count_] next write pos
267 std::vector<std::uint32_t> window_len_; // [node_count_] filled length
268 std::vector<std::int64_t> scratch_; // [window_blocks_] percentile scratch
269 std::vector<std::int64_t> record_scratch_; // [node_count_] external-record staging
270
271 std::vector<LiveDspNodeInfo> info_; // [node_count_]
272 std::uint64_t drained_ = 0;
273 std::uint64_t over_budget_blocks_ = 0;
274 LiveDspTelemetrySnapshot snapshot_;
275};
276
277} // namespace pulp::audio
LiveDspTelemetryBlockWriter() noexcept=default
LiveDspTelemetryNodeScope node(std::uint32_t node_slot) noexcept
Start timing node node_slot (0-based, < node_count).
void finish() noexcept
Publish the block.
bool active() const noexcept
Definition live_dsp_telemetry.hpp:161
RAII per-node timing scope, constructed inside begin_block()'s active block.
Definition live_dsp_telemetry.hpp:128
LiveDspTelemetryNodeScope() noexcept=default
The store. One producer (audio thread) and one consumer (drain/owner thread).
Definition live_dsp_telemetry.hpp:178
std::int64_t * external_record_scratch() noexcept
AUDIO THREAD.
Definition live_dsp_telemetry.hpp:215
friend class LiveDspTelemetryBlockWriter
Definition live_dsp_telemetry.hpp:230
bool prepare(const LiveDspTelemetryConfig &config, std::span< const LiveDspNodeInfo > nodes)
Allocate all storage for nodes.size() nodes and the ring.
std::uint64_t blocks_dropped() const noexcept
Definition live_dsp_telemetry.hpp:227
void drain() noexcept
NON-RT.
void inject_block(std::span< const std::int64_t > node_ns, std::int64_t graph_elapsed_ns, std::uint32_t frame_count, double sample_rate, std::span< const LiveDspSpectralDiagnostic > spectral={}) noexcept
AUDIO THREAD (or replay).
std::span< LiveDspSpectralDiagnostic > spectral_scratch() noexcept
Definition live_dsp_telemetry.hpp:207
bool prepared() const noexcept
Definition live_dsp_telemetry.hpp:191
std::uint32_t node_count() const noexcept
Definition live_dsp_telemetry.hpp:190
std::uint64_t blocks_written() const noexcept
Definition live_dsp_telemetry.hpp:226
friend class LiveDspTelemetryNodeScope
Definition live_dsp_telemetry.hpp:231
bool enabled() const noexcept
Definition live_dsp_telemetry.hpp:188
void set_enabled(bool enabled) noexcept
Definition live_dsp_telemetry.hpp:187
LiveDspTelemetryBlockWriter begin_block(std::uint32_t frame_count, double sample_rate) noexcept
AUDIO THREAD.
const LiveDspTelemetrySnapshot & latest() const noexcept
NON-RT, single reader. The latest published snapshot.
Definition live_dsp_telemetry.hpp:224
Definition analyzer_provider.hpp:12
LiveDspNodeKind
Coarse node classification, interned at prepare() time (never on the RT thread).
Definition live_dsp_telemetry.hpp:35
@ Gain
Definition live_dsp_telemetry.hpp:40
@ Plugin
Definition live_dsp_telemetry.hpp:39
@ AudioOutput
Definition live_dsp_telemetry.hpp:38
@ AudioInput
Definition live_dsp_telemetry.hpp:37
@ Unknown
Definition live_dsp_telemetry.hpp:36
@ Custom
Definition live_dsp_telemetry.hpp:43
@ Utility
Definition live_dsp_telemetry.hpp:44
@ MidiOutput
Definition live_dsp_telemetry.hpp:42
@ MidiInput
Definition live_dsp_telemetry.hpp:41
@ Unknown
Definition analyzer_provider.hpp:48
const char * to_string(LiveDspNodeKind kind) noexcept
STL namespace.
Immutable per-node identity, supplied to prepare() and copied into the store.
Definition live_dsp_telemetry.hpp:51
std::uint32_t input_ports
Definition live_dsp_telemetry.hpp:54
std::uint64_t node_id
Definition live_dsp_telemetry.hpp:52
void set_name(std::string_view value) noexcept
char name[64]
Definition live_dsp_telemetry.hpp:56
LiveDspNodeKind kind
Definition live_dsp_telemetry.hpp:53
std::uint32_t output_ports
Definition live_dsp_telemetry.hpp:55
Per-node rolling summary produced by drain().
Definition live_dsp_telemetry.hpp:80
std::int64_t p95_elapsed_ns
Definition live_dsp_telemetry.hpp:91
char name[64]
Definition live_dsp_telemetry.hpp:83
float last_budget_fraction
Definition live_dsp_telemetry.hpp:94
std::int64_t p50_elapsed_ns
Definition live_dsp_telemetry.hpp:90
std::int64_t min_elapsed_ns
Definition live_dsp_telemetry.hpp:87
std::int64_t jitter_ns
p95 - p50
Definition live_dsp_telemetry.hpp:93
std::int64_t mean_elapsed_ns
Definition live_dsp_telemetry.hpp:89
std::uint64_t node_id
Definition live_dsp_telemetry.hpp:81
std::uint64_t sample_count
blocks observed for this node
Definition live_dsp_telemetry.hpp:85
std::int64_t max_elapsed_ns
Definition live_dsp_telemetry.hpp:88
LiveDspNodeKind kind
Definition live_dsp_telemetry.hpp:82
std::int64_t p99_elapsed_ns
Definition live_dsp_telemetry.hpp:92
std::uint64_t over_budget_attributions
Definition live_dsp_telemetry.hpp:95
std::int64_t last_elapsed_ns
Definition live_dsp_telemetry.hpp:86
Definition live_dsp_telemetry.hpp:72
std::uint64_t root
Definition live_dsp_telemetry.hpp:73
std::uint64_t errors
Definition live_dsp_telemetry.hpp:74
std::uint64_t expected_sequence
Definition live_dsp_telemetry.hpp:73
std::int64_t first_error_position
Definition live_dsp_telemetry.hpp:75
std::uint64_t node
Definition live_dsp_telemetry.hpp:73
std::uint8_t first_error
Definition live_dsp_telemetry.hpp:76
std::int64_t latest_origin
Definition live_dsp_telemetry.hpp:75
std::uint64_t epoch
Definition live_dsp_telemetry.hpp:73
Definition live_dsp_telemetry.hpp:61
bool spectral_diagnostics
Definition live_dsp_telemetry.hpp:69
std::uint32_t ring_blocks
Number of block records the fixed-slot ring can hold before dropping.
Definition live_dsp_telemetry.hpp:63
std::uint32_t percentile_window_blocks
Per-node rolling window (in blocks) over which percentiles are computed.
Definition live_dsp_telemetry.hpp:65
float graph_overload_load
A block whose graph load reaches this fraction is counted "over budget" and attributed to its most ex...
Definition live_dsp_telemetry.hpp:68
Latest published summary. Owned by the store; valid until the next drain().
Definition live_dsp_telemetry.hpp:99
std::int64_t last_graph_elapsed_ns
Definition live_dsp_telemetry.hpp:113
std::int64_t last_available_ns
Definition live_dsp_telemetry.hpp:112
std::uint64_t blocks_written
Definition live_dsp_telemetry.hpp:105
std::vector< LiveDspNodeSummary > nodes
reused; never reallocated after prepare()
Definition live_dsp_telemetry.hpp:116
std::uint64_t blocks_dropped
Definition live_dsp_telemetry.hpp:107
float last_graph_load
Definition live_dsp_telemetry.hpp:114
bool enabled
Definition live_dsp_telemetry.hpp:101
std::uint64_t age_blocks
Lower bound at the drain's observation point.
Definition live_dsp_telemetry.hpp:120
std::uint32_t last_frame_count
Definition live_dsp_telemetry.hpp:111
std::uint64_t sequence_number
Definition live_dsp_telemetry.hpp:102
std::vector< LiveDspSpectralDiagnostic > spectral
Definition live_dsp_telemetry.hpp:117
std::uint64_t observed_drops
Definition live_dsp_telemetry.hpp:119
double sample_rate
Definition live_dsp_telemetry.hpp:110
std::uint64_t blocks_drained
Definition live_dsp_telemetry.hpp:106
std::uint64_t observed_block
Definition live_dsp_telemetry.hpp:118
bool available
Definition live_dsp_telemetry.hpp:100
std::uint32_t node_count
Definition live_dsp_telemetry.hpp:104
std::uint64_t graph_over_budget_blocks
Definition live_dsp_telemetry.hpp:108