Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
external_input.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cmath>
5#include <cstddef>
6#include <cstdint>
7#include <span>
8#include <type_traits>
9
10namespace pulp::runtime {
11
12enum class ExternalInputStatus : std::uint8_t { valid, invalid, unavailable, denied, paused };
13
14template <std::size_t Capacity> struct ExternalInputFrame {
15 static_assert(Capacity >= 1 && Capacity <= 64);
16 std::uint32_t source_id = 0;
17 std::uint32_t epoch = 0;
18 std::uint64_t sequence = 0;
19 std::uint64_t provider_time_ns = 0;
21 float confidence = 0.0f;
22 std::uint8_t count = 0;
23 std::array<float, Capacity> values{};
24 static constexpr std::size_t capacity() noexcept {
25 return Capacity;
26 }
27};
28
29static_assert(std::is_trivially_copyable_v<ExternalInputFrame<1>>);
30static_assert(std::is_trivially_copyable_v<ExternalInputFrame<64>>);
32
34 std::uint32_t source_id = 0;
35 float minimum_confidence = 0.0f;
36 std::uint64_t max_age_samples = 0;
37 std::uint8_t expected_count = 0;
38};
39
49
55
56template <std::size_t Capacity> class ExternalInputGate {
57 public:
59
60 ExternalInputVerdict submit(const Frame& frame, const ExternalInputPolicy& policy) noexcept {
61 if (policy.source_id != 0 && frame.source_id != policy.source_id) {
62 ++counters_.rejected_source;
64 }
65 if (has_seen_ && frame.epoch == epoch_ && frame.sequence == sequence_) {
66 ++counters_.unchanged;
68 }
69 // The ordering watermark outlives expire(): it is independent of whether a frame is held.
70 if (has_seen_ && (frame.epoch < epoch_ || (frame.epoch == epoch_ &&
71 (frame.sequence <= sequence_ ||
72 frame.provider_time_ns < provider_time_ns_)))) {
73 ++counters_.rejected_order;
75 }
76 if (frame.status != ExternalInputStatus::valid) {
77 last_status_ = frame.status;
78 advance_watermark(frame);
79 expire();
80 ++counters_.rejected_status;
82 }
83 if (frame.count == 0 || frame.count > Capacity ||
84 (policy.expected_count != 0 && frame.count != policy.expected_count) ||
85 !std::isfinite(frame.confidence)) {
86 ++counters_.rejected_malformed;
88 }
89 for (std::size_t i = 0; i < frame.count; ++i) {
90 if (!std::isfinite(frame.values[i])) {
91 ++counters_.rejected_malformed;
93 }
94 }
95 if (frame.confidence < 0.0f || frame.confidence > 1.0f ||
96 frame.confidence < policy.minimum_confidence) {
97 ++counters_.rejected_confidence;
99 }
100 values_ = frame.values;
101 count_ = frame.count;
102 has_frame_ = true;
103 advance_watermark(frame);
104 age_samples_ = 0;
105 last_status_ = frame.status;
106 ++counters_.accepted;
107 if (frame.epoch != prior_epoch_) {
108 ++counters_.epochs;
109 prior_epoch_ = frame.epoch;
110 }
112 }
113
114 bool advance(std::uint64_t samples, const ExternalInputPolicy& policy) noexcept {
115 if (!has_frame_ || policy.max_age_samples == 0)
116 return false;
117 age_samples_ = (UINT64_MAX - age_samples_ < samples) ? UINT64_MAX : age_samples_ + samples;
118 if (age_samples_ >= policy.max_age_samples) {
119 expire();
120 ++counters_.expired;
121 return true;
122 }
123 return false;
124 }
125 void expire() noexcept {
126 has_frame_ = false;
127 count_ = 0;
128 age_samples_ = 0;
129 }
130 bool valid() const noexcept {
131 return has_frame_;
132 }
133 std::span<const float> values() const noexcept {
134 return {values_.data(), static_cast<std::size_t>(has_frame_ ? count_ : 0)};
135 }
136 float value(std::size_t index, float fallback) const noexcept {
137 return has_frame_ && index < count_ ? values_[index] : fallback;
138 }
139 std::uint32_t epoch() const noexcept {
140 return epoch_;
141 }
142 std::uint64_t sequence() const noexcept {
143 return sequence_;
144 }
145 std::uint64_t age_samples() const noexcept {
146 return age_samples_;
147 }
149 return last_status_;
150 }
151 const ExternalInputCounters& counters() const noexcept {
152 return counters_;
153 }
154 void reset_counters() noexcept {
155 counters_ = {};
156 }
157
158 private:
159 void advance_watermark(const Frame& frame) noexcept {
160 has_seen_ = true;
161 epoch_ = frame.epoch;
162 sequence_ = frame.sequence;
163 provider_time_ns_ = frame.provider_time_ns;
164 }
165 std::array<float, Capacity> values_{};
166 ExternalInputCounters counters_{};
168 std::uint32_t epoch_ = 0, prior_epoch_ = 0;
169 std::uint64_t sequence_ = 0, provider_time_ns_ = 0, age_samples_ = 0;
170 std::uint8_t count_ = 0;
171 bool has_frame_ = false;
172 bool has_seen_ = false;
173};
174
175} // namespace pulp::runtime
Definition external_input.hpp:56
ExternalInputFrame< Capacity > Frame
Definition external_input.hpp:58
std::uint64_t age_samples() const noexcept
Definition external_input.hpp:145
void reset_counters() noexcept
Definition external_input.hpp:154
bool valid() const noexcept
Definition external_input.hpp:130
void expire() noexcept
Definition external_input.hpp:125
const ExternalInputCounters & counters() const noexcept
Definition external_input.hpp:151
std::uint64_t sequence() const noexcept
Definition external_input.hpp:142
float value(std::size_t index, float fallback) const noexcept
Definition external_input.hpp:136
std::uint32_t epoch() const noexcept
Definition external_input.hpp:139
bool advance(std::uint64_t samples, const ExternalInputPolicy &policy) noexcept
Definition external_input.hpp:114
ExternalInputStatus last_status() const noexcept
Definition external_input.hpp:148
ExternalInputVerdict submit(const Frame &frame, const ExternalInputPolicy &policy) noexcept
Definition external_input.hpp:60
std::span< const float > values() const noexcept
Definition external_input.hpp:133
Definition generated_event_source.hpp:33
ExternalInputFrame< 1 > ExternalInputScalar
Definition external_input.hpp:31
ExternalInputVerdict
Definition external_input.hpp:40
@ rejected_malformed
Definition external_input.hpp:46
@ rejected_source
Definition external_input.hpp:44
@ accepted
Definition external_input.hpp:41
@ rejected_status
Definition external_input.hpp:43
@ rejected_order
Definition external_input.hpp:45
@ unchanged
Definition external_input.hpp:42
@ rejected_confidence
Definition external_input.hpp:47
ExternalInputStatus
Definition external_input.hpp:12
@ unavailable
Definition external_input.hpp:12
@ denied
Definition external_input.hpp:12
@ valid
Definition external_input.hpp:12
@ paused
Definition external_input.hpp:12
@ invalid
Definition external_input.hpp:12
Definition external_input.hpp:50
std::uint64_t accepted
Definition external_input.hpp:51
std::uint64_t rejected_confidence
Definition external_input.hpp:52
std::uint64_t rejected_source
Definition external_input.hpp:51
std::uint64_t rejected_status
Definition external_input.hpp:51
std::uint64_t unchanged
Definition external_input.hpp:51
std::uint64_t expired
Definition external_input.hpp:52
std::uint64_t rejected_order
Definition external_input.hpp:52
std::uint64_t rejected_malformed
Definition external_input.hpp:52
std::uint64_t epochs
Definition external_input.hpp:53
Definition external_input.hpp:14
static constexpr std::size_t capacity() noexcept
Definition external_input.hpp:24
float confidence
Definition external_input.hpp:21
std::uint32_t epoch
Definition external_input.hpp:17
std::uint64_t provider_time_ns
Definition external_input.hpp:19
std::uint64_t sequence
Definition external_input.hpp:18
std::uint32_t source_id
Definition external_input.hpp:16
ExternalInputStatus status
Definition external_input.hpp:20
std::array< float, Capacity > values
Definition external_input.hpp:23
std::uint8_t count
Definition external_input.hpp:22
Definition external_input.hpp:33
std::uint64_t max_age_samples
Definition external_input.hpp:36
std::uint8_t expected_count
Definition external_input.hpp:37
float minimum_confidence
Definition external_input.hpp:35
std::uint32_t source_id
Definition external_input.hpp:34