Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
generated_event_source.hpp
Go to the documentation of this file.
1#pragma once
2
18
20#include <pulp/midi/ump.hpp>
24
25#include <array>
26#include <atomic>
27#include <cstddef>
28#include <cstdint>
29#include <memory>
30#include <span>
31#include <vector>
32
33namespace pulp::runtime {
34class SpscRingIndex;
35}
36
37namespace pulp::playback {
38
39using GeneratedEventCommitGeneration = std::uint64_t;
40using GeneratedEventRevision = std::uint64_t;
41
45 std::uint64_t playback_epoch = 0;
48
49 constexpr bool operator==(const GeneratedEventSpan&) const = default;
50};
51
58
65
67 static constexpr std::size_t maximum_steps = 3;
73 std::uint8_t count = static_cast<std::uint8_t>(maximum_steps);
74
75 std::span<const GeneratedEventDegradation> active() const noexcept {
76 const auto active_count = count <= maximum_steps ? static_cast<std::size_t>(count) : 0;
77 return {steps.data(), active_count};
78 }
79};
80
89
107
115
126
129 std::size_t committed_batches = 0;
130
131 constexpr explicit operator bool() const noexcept {
133 }
134};
135
142
153
155 public:
158
161
164
169
173 bool begin_playback_epoch(std::uint64_t playback_epoch) noexcept;
174
176 void release() noexcept;
177
182 std::span<const GeneratedEvent> events) noexcept;
183
188 timebase::MonotonicBeat boundary,
189 GeneratedEventCommitGeneration generation) noexcept;
190
195 std::span<GeneratedEvent> output) noexcept;
196
201 void record_deadline_met() noexcept;
203
204 bool prepared() const noexcept {
205 return prepared_;
206 }
207
208 struct Stats {
209 std::uint64_t committed_batches = 0;
210 std::uint64_t consumed_batches = 0;
211 std::uint64_t starvation_events = 0;
212 std::uint64_t lagged_ticks = 0;
213 std::uint64_t late_batches = 0;
214 std::uint64_t output_overflows = 0;
215 std::uint64_t deadline_misses = 0;
216 std::array<std::uint64_t, GeneratedEventDegradationLadder::maximum_steps>
218 std::size_t committed_batches_ready = 0;
219 };
220
221 Stats stats() const noexcept;
222
223 private:
224 struct BatchSlot {
225 GeneratedEventSpan span{};
226 GeneratedEventRevision revision = 0;
227 GeneratedEventCommitGeneration commit_generation = 0;
228 std::size_t event_count = 0;
229 };
230
231 struct ElapsedFrontierSnapshot {
232 std::uint64_t epoch = 0;
233 std::int64_t tick = 0;
234 bool present = false;
235 };
236
237 bool valid_span(const GeneratedEventSpan& span) const noexcept;
238 bool is_quantized(timebase::MonotonicBeat boundary) const noexcept;
239 bool valid_events(const GeneratedEventSpan& span,
240 std::span<const GeneratedEvent> events) const noexcept;
241 void publish_elapsed(const GeneratedEventSpan& span) noexcept;
242 bool elapsed_frontier(std::uint64_t& epoch, std::int64_t& tick) const noexcept;
243 GeneratedEvent* staged_event_storage(std::size_t index) noexcept;
244 GeneratedEvent* committed_event_storage(std::size_t index) noexcept;
245
246 GeneratedEventSourceConfig config_{};
247 std::vector<BatchSlot> staged_{};
248 std::vector<GeneratedEvent> staged_events_{};
249 std::size_t staged_count_ = 0;
250 std::vector<BatchSlot> committed_{};
251 std::vector<GeneratedEvent> committed_events_{};
252 std::unique_ptr<runtime::SpscRingIndex> committed_ring_{};
253
254 std::uint64_t committed_epoch_ = 0;
255 timebase::MonotonicBeat committed_through_{};
256 GeneratedEventCommitGeneration last_commit_generation_ = 0;
257 std::uint64_t active_epoch_ = 0;
258 bool has_committed_frontier_ = false;
259 bool has_active_epoch_ = false;
260 bool prepared_ = false;
261 std::atomic<std::uint8_t> consecutive_deadline_misses_{0};
262
263 // Audio-thread-owned mirror prevents an invalid pull from regressing the
264 // atomically published producer frontier.
265 std::uint64_t consumer_elapsed_epoch_ = 0;
266 std::int64_t consumer_elapsed_tick_ = 0;
267 bool has_consumer_elapsed_frontier_ = false;
268
269 // One audio writer, one producer reader. Use the shared primitive so its
270 // ARM-safe read fence and coherence tests govern this frontier too.
271 runtime::SeqLock<ElapsedFrontierSnapshot> elapsed_frontier_{};
272 std::atomic<std::uint8_t> current_degradation_index_{
273 static_cast<std::uint8_t>(GeneratedEventDegradationLadder::maximum_steps)};
274 std::atomic<std::uint64_t> committed_batches_{0};
275 std::atomic<std::uint64_t> consumed_batches_{0};
276 std::atomic<std::uint64_t> starvation_events_{0};
277 std::atomic<std::uint64_t> lagged_ticks_{0};
278 std::atomic<std::uint64_t> late_batches_{0};
279 std::atomic<std::uint64_t> output_overflows_{0};
280 std::atomic<std::uint64_t> deadline_misses_{0};
281 std::array<std::atomic<std::uint64_t>, GeneratedEventDegradationLadder::maximum_steps>
282 degradation_uses_{};
283};
284
285} // namespace pulp::playback
bool prepare(const GeneratedEventSourceConfig &config)
Quiescent control thread.
GeneratedEventSource(const GeneratedEventSource &)=delete
GeneratedEventDegradation record_deadline_miss() noexcept
Select or reset producer-declared fallback policy.
GeneratedEventPullResult pull(GeneratedEventSpan requested, std::span< GeneratedEvent > output) noexcept
Audio thread.
GeneratedEventSource & operator=(const GeneratedEventSource &)=delete
void release() noexcept
Quiescent control thread. No producer or consumer may be active.
GeneratedEventStageResult stage(GeneratedEventSpan span, GeneratedEventRevision revision, std::span< const GeneratedEvent > events) noexcept
Producer thread.
static constexpr audio::RtSafetyClass pull_rt_safety_class
Definition generated_event_source.hpp:156
bool prepared() const noexcept
Definition generated_event_source.hpp:204
GeneratedEventDegradation current_degradation() const noexcept
bool begin_playback_epoch(std::uint64_t playback_epoch) noexcept
Quiescent control thread.
GeneratedEventCommitResult commit_through(std::uint64_t playback_epoch, timebase::MonotonicBeat boundary, GeneratedEventCommitGeneration generation) noexcept
Producer thread.
Definition spsc_ring_index.hpp:42
RtSafetyClass
Definition rt_safety_contract.hpp:11
@ AudioCallbackSafeAfterPrepare
Definition rt_safety_contract.hpp:13
Definition child_process_manager.hpp:18
Definition audio_renderer.hpp:20
GeneratedEventCommitCode
Definition generated_event_source.hpp:116
@ InvalidBoundary
Definition generated_event_source.hpp:121
@ StaleGeneration
Definition generated_event_source.hpp:123
@ NotPrepared
Definition generated_event_source.hpp:118
@ CommitRingFull
Definition generated_event_source.hpp:124
@ Committed
Definition generated_event_source.hpp:117
@ InvalidGeneration
Definition automation_program.hpp:27
std::uint64_t GeneratedEventRevision
Definition generated_event_source.hpp:40
std::uint64_t GeneratedEventCommitGeneration
Definition generated_event_source.hpp:39
@ NotPrepared
Definition automation_recording.hpp:30
@ None
Definition automation_recording.hpp:29
GeneratedEventPullCode
Definition generated_event_source.hpp:136
@ Starved
Definition generated_event_source.hpp:138
@ InvalidRequest
Definition generated_event_source.hpp:140
@ Ready
Definition generated_event_source.hpp:137
GeneratedEventStageCode
Definition generated_event_source.hpp:90
@ NotQuantized
Definition generated_event_source.hpp:97
@ OutOfOrder
Definition generated_event_source.hpp:101
@ InvalidSpan
Definition generated_event_source.hpp:96
@ StagingCapacityExceeded
Definition generated_event_source.hpp:105
@ NotPrepared
Definition generated_event_source.hpp:93
@ InvalidEvent
Definition generated_event_source.hpp:103
@ Staged
Definition generated_event_source.hpp:91
@ OverlappingSpan
Definition generated_event_source.hpp:102
@ WrongEpoch
Definition generated_event_source.hpp:95
@ FrozenSpan
Definition generated_event_source.hpp:100
@ EventCapacityExceeded
Definition generated_event_source.hpp:104
@ StaleRevision
Definition generated_event_source.hpp:99
@ Revised
Definition generated_event_source.hpp:92
@ InvalidRevision
Definition generated_event_source.hpp:98
@ EpochNotStarted
Definition generated_event_source.hpp:94
@ OutputOverflow
Definition external_sync.hpp:99
GeneratedEventDegradation
Definition generated_event_source.hpp:59
@ None
Definition generated_event_source.hpp:60
@ UseSkeleton
Definition generated_event_source.hpp:62
@ Silence
Definition generated_event_source.hpp:63
@ RepeatLastCommitted
Definition generated_event_source.hpp:61
Definition generated_event_source.hpp:33
Definition beat_division.hpp:11
STL namespace.
Lock-free sequence-lock for coherent multi-field snapshots.
Definition ump.hpp:84
Definition generated_event_source.hpp:127
GeneratedEventCommitCode code
Definition generated_event_source.hpp:128
std::size_t committed_batches
Definition generated_event_source.hpp:129
Definition generated_event_source.hpp:66
std::span< const GeneratedEventDegradation > active() const noexcept
Definition generated_event_source.hpp:75
std::array< GeneratedEventDegradation, maximum_steps > steps
Definition generated_event_source.hpp:68
static constexpr std::size_t maximum_steps
Definition generated_event_source.hpp:67
std::uint8_t count
Definition generated_event_source.hpp:73
Definition generated_event_source.hpp:143
std::size_t event_count
Definition generated_event_source.hpp:145
std::uint64_t lagged_ticks
Definition generated_event_source.hpp:147
GeneratedEventDegradation degradation
Producer-selected fallback policy, or None before any declared miss.
Definition generated_event_source.hpp:149
GeneratedEventPullCode code
Definition generated_event_source.hpp:144
bool flush_active_notes
The downstream renderer must emit its bounded all-notes-off/reset path.
Definition generated_event_source.hpp:151
GeneratedEventCommitGeneration commit_generation
Definition generated_event_source.hpp:146
Definition generated_event_source.hpp:81
GeneratedEventDegradationLadder degradation
Definition generated_event_source.hpp:87
timeline::LaunchQuantize commit_quantize
Non-immediate grid whose exact boundaries may freeze staged batches.
Definition generated_event_source.hpp:86
std::size_t committed_batch_capacity
Definition generated_event_source.hpp:82
std::size_t staged_batch_capacity
Definition generated_event_source.hpp:83
std::size_t maximum_events_per_batch
Definition generated_event_source.hpp:84
Definition generated_event_source.hpp:208
std::uint64_t output_overflows
Definition generated_event_source.hpp:214
std::size_t committed_batches_ready
Definition generated_event_source.hpp:218
std::uint64_t committed_batches
Definition generated_event_source.hpp:209
std::uint64_t lagged_ticks
Definition generated_event_source.hpp:212
std::uint64_t consumed_batches
Definition generated_event_source.hpp:210
std::array< std::uint64_t, GeneratedEventDegradationLadder::maximum_steps > degradation_uses
Definition generated_event_source.hpp:217
std::uint64_t deadline_misses
Definition generated_event_source.hpp:215
std::uint64_t starvation_events
Definition generated_event_source.hpp:211
std::uint64_t late_batches
Definition generated_event_source.hpp:213
A half-open span on the transport's non-looping clock.
Definition generated_event_source.hpp:44
constexpr bool operator==(const GeneratedEventSpan &) const =default
timebase::MonotonicBeat end
Definition generated_event_source.hpp:47
timebase::MonotonicBeat start
Definition generated_event_source.hpp:46
std::uint64_t playback_epoch
Definition generated_event_source.hpp:45
Definition generated_event_source.hpp:108
GeneratedEventStageCode code
Definition generated_event_source.hpp:109
One value-owned generated event.
Definition generated_event_source.hpp:54
timebase::TickDuration offset
Definition generated_event_source.hpp:55
midi::UmpPacket packet
Definition generated_event_source.hpp:56
Definition tick.hpp:71
Definition tick.hpp:56
Musical-boundary quantization for one launch.
Definition clip_launch.hpp:40