Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
ump_buffer.hpp
Go to the documentation of this file.
1#pragma once
2
14
15#include <pulp/midi/ump.hpp>
16#include <algorithm>
17#include <cstddef>
18#include <cstdint>
19#include <limits>
20#include <vector>
21
22namespace pulp::midi {
23
25struct UmpEvent {
27 int32_t sample_offset = 0;
28};
29
41class UmpBuffer {
42 public:
44 reserve(kInitialCapacity);
45 }
46 UmpBuffer(const UmpBuffer& other)
47 : events_(other.events_), limit_to_reserved_capacity_(other.limit_to_reserved_capacity_),
48 dropped_events_(other.dropped_events_) {
49 reserve(other.capacity());
50 }
51 UmpBuffer& operator=(const UmpBuffer& other) {
52 if (this != &other) {
53 events_ = other.events_;
54 limit_to_reserved_capacity_ = other.limit_to_reserved_capacity_;
55 dropped_events_ = other.dropped_events_;
56 reserve(other.capacity());
57 }
58 return *this;
59 }
60 UmpBuffer(UmpBuffer&&) noexcept = default;
61 UmpBuffer& operator=(UmpBuffer&&) noexcept = default;
62
63 bool add(const UmpEvent& e) {
64 if (!can_append()) {
65 record_drop();
66 return false;
67 }
68 events_.push_back(e);
69 prepare_sort_after_growth();
70 return true;
71 }
72 bool add(UmpEvent&& e) {
73 if (!can_append()) {
74 record_drop();
75 return false;
76 }
77 events_.push_back(std::move(e));
78 prepare_sort_after_growth();
79 return true;
80 }
81 bool add(const UmpPacket& p, int32_t sample_offset = 0) {
82 if (!can_append()) {
83 record_drop();
84 return false;
85 }
86 events_.push_back({p, sample_offset});
87 prepare_sort_after_growth();
88 return true;
89 }
90
91 void clear() {
92 events_.clear();
93 dropped_events_ = 0;
94 }
95 bool empty() const { return events_.empty(); }
96 std::size_t size() const { return events_.size(); }
97 std::size_t capacity() const { return events_.capacity(); }
98 std::uint32_t dropped_event_count() const { return dropped_events_; }
99 void reserve(std::size_t capacity) {
100 events_.reserve(capacity);
101 sort_indices_.reserve(events_.capacity());
102 sort_events_.reserve(events_.capacity());
103 }
104 void set_realtime_capacity_limit(bool enabled = true) {
105 limit_to_reserved_capacity_ = enabled;
106 }
107 bool realtime_capacity_limited() const { return limit_to_reserved_capacity_; }
108
112 void sort() {
113 const auto count = events_.size();
114 if (count < 2)
115 return;
116 sort_indices_.resize(count);
117 for (std::size_t i = 0; i < count; ++i)
118 sort_indices_[i] = i;
119 std::sort(sort_indices_.begin(), sort_indices_.end(), [this](std::size_t a, std::size_t b) {
120 if (events_[a].sample_offset != events_[b].sample_offset)
121 return events_[a].sample_offset < events_[b].sample_offset;
122 return a < b;
123 });
124 sort_events_.resize(count);
125 for (std::size_t i = 0; i < count; ++i)
126 sort_events_[i] = events_[sort_indices_[i]];
127 events_.swap(sort_events_);
128 }
129
130 auto begin() { return events_.begin(); }
131 auto end() { return events_.end(); }
132 auto begin() const { return events_.begin(); }
133 auto end() const { return events_.end(); }
134
135 const UmpEvent& operator[](std::size_t i) const { return events_[i]; }
136
137 private:
138 void prepare_sort_after_growth() {
139 if (!limit_to_reserved_capacity_) {
140 sort_indices_.reserve(events_.capacity());
141 sort_events_.reserve(events_.capacity());
142 }
143 }
144 bool can_append() const {
145 return !limit_to_reserved_capacity_ || events_.size() < events_.capacity();
146 }
147 void record_drop() {
148 if (dropped_events_ < std::numeric_limits<std::uint32_t>::max()) {
149 ++dropped_events_;
150 }
151 }
152
153 static constexpr std::size_t kInitialCapacity = 128;
154 std::vector<UmpEvent> events_;
155 std::vector<std::size_t> sort_indices_;
156 std::vector<UmpEvent> sort_events_;
157 bool limit_to_reserved_capacity_ = false;
158 std::uint32_t dropped_events_ = 0;
159};
160
161} // namespace pulp::midi
UmpBuffer(const UmpBuffer &other)
Definition ump_buffer.hpp:46
UmpBuffer & operator=(const UmpBuffer &other)
Definition ump_buffer.hpp:51
void set_realtime_capacity_limit(bool enabled=true)
Definition ump_buffer.hpp:104
std::size_t capacity() const
Definition ump_buffer.hpp:97
auto end() const
Definition ump_buffer.hpp:133
bool add(const UmpEvent &e)
Definition ump_buffer.hpp:63
void reserve(std::size_t capacity)
Definition ump_buffer.hpp:99
auto begin()
Definition ump_buffer.hpp:130
const UmpEvent & operator[](std::size_t i) const
Definition ump_buffer.hpp:135
bool add(UmpEvent &&e)
Definition ump_buffer.hpp:72
void sort()
Sort by sample offset, preserving arrival order for equal offsets.
Definition ump_buffer.hpp:112
UmpBuffer(UmpBuffer &&) noexcept=default
UmpBuffer()
Definition ump_buffer.hpp:43
auto end()
Definition ump_buffer.hpp:131
std::size_t size() const
Definition ump_buffer.hpp:96
std::uint32_t dropped_event_count() const
Definition ump_buffer.hpp:98
bool add(const UmpPacket &p, int32_t sample_offset=0)
Definition ump_buffer.hpp:81
bool realtime_capacity_limited() const
Definition ump_buffer.hpp:107
bool empty() const
Definition ump_buffer.hpp:95
void clear()
Definition ump_buffer.hpp:91
auto begin() const
Definition ump_buffer.hpp:132
Definition custom_node_events.hpp:26
One UMP packet with a block-relative sample offset.
Definition ump_buffer.hpp:25
UmpPacket packet
Definition ump_buffer.hpp:26
int32_t sample_offset
Definition ump_buffer.hpp:27
Definition ump.hpp:84