51 void reset() noexcept { offset_ = 0; }
52 std::size_t
size_bytes() const noexcept {
return memory_.size(); }
53 std::size_t
used_bytes() const noexcept {
return offset_; }
55 return offset_ <= memory_.size() ? memory_.size() - offset_ : 0;
57 bool empty() const noexcept {
return memory_.empty(); }
60 std::size_t alignment)
noexcept {
61 if (byte_count == 0)
return {};
62 if (alignment == 0 || !std::has_single_bit(alignment))
return {};
63 if (memory_.empty())
return {};
65 const auto base =
reinterpret_cast<std::uintptr_t
>(memory_.data());
66 const auto current = base + offset_;
67 const auto aligned = align_up(current, alignment);
68 const auto aligned_offset =
static_cast<std::size_t
>(aligned - base);
69 if (aligned_offset > memory_.size())
return {};
70 if (byte_count > memory_.size() - aligned_offset)
return {};
72 offset_ = aligned_offset + byte_count;
73 return memory_.subspan(aligned_offset, byte_count);
78 static_assert(std::is_trivially_copyable_v<T>,
79 "scratch spans are for plain DSP scratch types");
80 if (count == 0)
return {};
81 if (count > std::numeric_limits<std::size_t>::max() /
sizeof(T))
return {};
83 if (bytes.empty())
return {};
84 return {
reinterpret_cast<T*
>(bytes.data()), count};
88 static std::uintptr_t align_up(std::uintptr_t value,
89 std::size_t alignment)
noexcept {
90 const auto mask =
static_cast<std::uintptr_t
>(alignment - 1);
91 return (value + mask) & ~mask;
94 std::span<std::byte> memory_;
95 std::size_t offset_ = 0;
127 :
input.num_channels();
132 :
input.num_samples();
153 bool active =
true) noexcept {
154 if (size_ >= buses_.size())
return false;
162 bool active =
true) noexcept {
163 if (size_ >= buses_.size())
return false;
168 void clear() noexcept { size_ = 0; }
169 std::size_t
size() const noexcept {
return size_; }
170 std::size_t
capacity() const noexcept {
return buses_.size(); }
171 bool empty() const noexcept {
return size_ == 0; }
173 std::span<BusBuffer>
buses() noexcept {
return {buses_.data(), size_}; }
174 std::span<const BusBuffer>
buses() const noexcept {
return {buses_.data(), size_}; }
177 for (
auto& bus :
buses()) {
178 if (bus.direction == direction && bus.name == name)
return &bus;
184 for (
const auto& bus :
buses()) {
185 if (bus.direction == direction && bus.name == name)
return &bus;
192 for (
auto& bus :
buses()) {
193 if (bus.direction == direction && bus.role == role)
return &bus;
200 for (
const auto& bus :
buses()) {
201 if (bus.direction == direction && bus.role == role)
return &bus;
207 for (
const auto& bus :
buses()) {
208 if (bus.active && bus.num_frames() != frame_count)
return false;
214 std::array<BusBuffer, kMaxBuses> buses_{};
215 std::size_t size_ = 0;
230template <
typename SampleType>
244 return info.declared_channels >= 0 &&
249 if (!
active() ||
buffer.num_channels() == 0)
return true;
250 for (std::size_t ch = 0; ch <
buffer.num_channels(); ++ch) {
251 if (
buffer.channel_ptr(ch) ==
nullptr)
return false;
258template <
typename SampleType>
265 std::size_t
size() const noexcept {
return buses_.size(); }
266 bool empty() const noexcept {
return buses_.empty(); }
269 return buses_[index];
272 return buses_[index];
276 return find(role, 0);
280 return find(role, 0);
284 std::size_t occurrence)
noexcept {
285 std::size_t seen = 0;
286 for (
auto& bus : buses_) {
287 if (bus.info.role != role)
continue;
288 if (seen == occurrence)
return &bus;
296 std::size_t occurrence)
const noexcept {
297 std::size_t seen = 0;
298 for (
const auto& bus : buses_) {
299 if (bus.info.role != role)
continue;
300 if (seen == occurrence)
return &bus;
307 for (
auto& bus : buses_) {
308 if (bus.info.index == index)
return &bus;
314 std::size_t index)
const noexcept {
315 for (
const auto& bus : buses_) {
316 if (bus.info.index == index)
return &bus;
322 for (
auto& bus : buses_) {
323 if (bus.info.name == name)
return &bus;
329 std::string_view name)
const noexcept {
330 for (
const auto& bus : buses_) {
331 if (bus.info.name == name)
return &bus;
349 std::size_t
count = 0;
350 for (
const auto& bus : buses_) {
351 if (bus.active()) ++
count;
357 std::size_t total = 0;
358 for (
const auto& bus : buses_) {
359 if (bus.info.role == role) ++total;
365 std::size_t total = 0;
366 for (
const auto& bus : buses_) {
367 if (bus.info.role == role && bus.active()) ++total;
373 for (
const auto& bus : buses_) {
374 if (!bus.matches_declared_layout())
return false;
380 for (
const auto& bus : buses_) {
381 if (!bus.has_channel_storage())
return false;
387 std::span<ProcessBusBufferView<SampleType>> buses_;
391template <
typename SampleType =
float>
397 if (
auto* bus =
inputs.main(); bus && bus->active())
return &bus->buffer;
402 if (
auto* bus =
outputs.main(); bus && bus->active())
return &bus->buffer;
407 if (
auto* bus =
inputs.sidechain(); bus && bus->active())
return &bus->buffer;
412 return inputs.layouts_match_descriptors() &&
413 outputs.layouts_match_descriptors();
417 return inputs.active_buses_have_storage() &&
418 outputs.active_buses_have_storage();
434 bool any() const noexcept {
440 std::uint32_t
total() const noexcept {
479 std::span<const state::ParameterEvent>
parameters() const noexcept {
481 : std::span<const state::ParameterEvent>{};
540 for (
const auto& lane :
events->audio_rate_modulations) {
541 if (lane.values.size() !=
frame_count)
return false;
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
Collection of timestamped MIDI events within a single audio buffer period.
Definition buffer.hpp:31
A time-ordered list of per-note expression events for one block.
Definition mpe_buffer.hpp:51
A time-ordered list of UMP events for one audio block.
Definition ump_buffer.hpp:41
Definition parameter_event_queue.hpp:82
Sample-accurate MPE expression event stream.
Process context — passed every audio callback with transport state.
Definition process_context.hpp:89
Sample-accurate MIDI 2.0 UMP packet stream.