The shared adapter-boundary core. More...
#include <pulp/format/processor.hpp>#include <pulp/format/detail/playhead_diff.hpp>#include <pulp/signal/delay_line.hpp>#include <pulp/state/parameter_event_queue.hpp>#include <pulp/state/store.hpp>#include <array>#include <cmath>#include <cstddef>#include <cstdint>#include <cstring>#include <span>#include <vector>Go to the source code of this file.
Classes | |
| struct | pulp::format::boundary::HostTransport |
| Format-neutral transport snapshot, already decoded from a host playhead into canonical units (quarter-note beats, samples, real BPM). More... | |
| class | pulp::format::boundary::LatencyCompensatedBypassT< MaxChannels > |
| Per-channel dry-signal delay used by an adapter's bypass path. More... | |
| struct | pulp::format::boundary::ParamSnapshotState |
| Generation-gated pre-process snapshot: which generation it was taken at and whether it can be trusted. More... | |
| struct | pulp::format::boundary::MpeSidecar |
| Owns the MPE tracker + expression buffer + inbound-offset cursor an adapter wraps around its MIDI decode, plus the descriptor opt-in flag. More... | |
Namespaces | |
| namespace | pulp |
| namespace | pulp::format |
| What the product grants a device: the quota table indexed by capability tier and live thermal state. | |
| namespace | pulp::format::boundary |
Typedefs | |
| using | pulp::format::boundary::LatencyCompensatedBypass = LatencyCompensatedBypassT<kBoundaryMaxChannels> |
Functions | |
| void | pulp::format::boundary::copy_f32_to_f64 (const float *src, double *dst, std::uint32_t count) noexcept |
| Widen count floats src → dst as doubles. No-op on a null pointer. | |
| void | pulp::format::boundary::copy_f64_to_f32 (const double *src, float *dst, std::uint32_t count) noexcept |
| Narrow count doubles src → dst as floats. No-op on a null pointer. | |
| void | pulp::format::boundary::zero_f64 (double *dst, std::uint32_t count) noexcept |
| Zero count doubles. No-op on a null pointer. | |
| void | pulp::format::boundary::apply_host_transport (ProcessContext &ctx, const HostTransport &transport, detail::PlayheadSnapshot &snapshot) noexcept |
Write transport into ctx's transport fields, derive the bar when the host did not supply one, then diff ctx against snapshot to populate tempo_changed / time_sig_changed / transport_changed / transport_started / transport_jump and advance the snapshot in place. | |
| template<std::size_t MaxChannels> | |
| void | pulp::format::boundary::render_bypass_passthrough (LatencyCompensatedBypassT< MaxChannels > &bypass, float *const *out_ptrs, int out_channels, const float *const *in_ptrs, int in_channels, std::uint32_t count) |
Render one bypassed block: copy main input → output per channel, latency- compensated through bypass so the dry signal stays sample-aligned with the host's plugin-delay-compensation, and zero any output channel without a matching input. | |
| bool | pulp::format::boundary::apply_param_value (state::ParameterEventQueue &queue, state::StateStore &store, state::ParamID id, std::int32_t sample_offset, float value) |
| Apply one incoming host parameter-value event, the way every adapter must. | |
| std::size_t | pulp::format::boundary::find_param_index (std::span< const state::ParamInfo > all_params, state::ParamID id) noexcept |
Position of id within all_params, or kParamIndexNotFound. | |
| void | pulp::format::boundary::snapshot_param_values (const state::StateStore &store, std::span< const state::ParamInfo > all_params, std::vector< float > &snapshot) |
Capture every parameter's current value into snapshot, positionally aligned with all_params, so a post-process() diff can spot the values the processor changed. | |
| template<typename AfterRead = void (*)()> | |
| void | pulp::format::boundary::refresh_param_snapshot (const state::StateStore &store, std::span< const state::ParamInfo > all_params, std::vector< float > &snapshot, ParamSnapshotState &state, std::uint64_t generation, AfterRead &&after_read=[] {}) |
Brings snapshot up to date for a block whose store generation is generation, re-reading every value only when a write landed since the last trusted snapshot. | |
| bool | pulp::format::boundary::changed_since_snapshot (float current, float snapshotted) noexcept |
True when current differs from snapshotted, compared bitwise. | |
Variables | |
| constexpr std::size_t | pulp::format::boundary::kBoundaryMaxChannels = 8 |
| Channel ceiling — the single source of truth for the per-bus channel count every adapter caps at. | |
| constexpr std::size_t | pulp::format::boundary::kParamIndexNotFound = static_cast<std::size_t>(-1) |
| Index returned by find_param_index when the id is not registered. | |
The shared adapter-boundary core.
Every per-format plugin adapter (CLAP, VST3, AU v2/v3, AAX, LV2, WAM/WCLAP, standalone) sits between a host ABI and one Processor. The host-ABI glue is genuinely format-specific — the event structs, the pointer layouts, the transport flag bits all differ. But the boundary logic those adapters wrap around the glue is identical, and it was copy-pasted at different fidelity per adapter with nothing that noticed when a copy drifted. This header is where that logic is consolidated as adapters migrate onto it. The adoption is deliberately per-component and still partial:
Real-time contract. Everything here runs on the audio/render thread and is allocation-, lock-, and syscall-free after prepare(): the only place that touches the heap is LatencyCompensatedBypass::prepare(), which the adapter calls at activate/setup time off the audio thread. The functions are pure and header-only so the parity-matrix test (test_adapter_boundary_ parity.cpp) can drive one processor through every format's boundary profile and assert identical observable behavior without standing up a host SDK.