|
| void | 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 | 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 | zero_f64 (double *dst, std::uint32_t count) noexcept |
| | Zero count doubles. No-op on a null pointer.
|
| void | 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 | 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 | 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 | find_param_index (std::span< const state::ParamInfo > all_params, state::ParamID id) noexcept |
| | Position of id within all_params, or kParamIndexNotFound.
|
| void | 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 | 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 | changed_since_snapshot (float current, float snapshotted) noexcept |
| | True when current differs from snapshotted, compared bitwise.
|
| void pulp::format::boundary::apply_host_transport |
( |
ProcessContext & | ctx, |
|
|
const HostTransport & | transport, |
|
|
detail::PlayheadSnapshot & | snapshot ) |
|
inlinenoexcept |
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.
Pure aside from the in-place snapshot update; no allocation. The snapshot is the adapter's per-instance previous-block state (a PlayheadSnapshot member), so a first block after construction raises no spurious change flags. ctx.sample_rate / ctx.num_samples must already be set — the diff uses them to tell a continuous beat advance from a seek.
| bool pulp::format::boundary::changed_since_snapshot |
( |
float | current, |
|
|
float | snapshotted ) |
|
inlinenoexcept |
True when current differs from snapshotted, compared bitwise.
Deliberately not current != snapshotted. The question this answers is "did
the stored bits move", not "are these numerically equal", and the two differ at the edges every parameter store hits eventually: a NaN parameter would compare unequal to itself under != and be republished on every single block forever, while +0.0/-0.0 compare equal under != and would silently drop a real store write. RT-safe.
Position of id within all_params, or kParamIndexNotFound.
The position — not the id — is the key for every per-block scratch vector an adapter sizes off all_params() (the value snapshot, the skip-set, the per-parameter host queue cache), so a publication path holding an id has to resolve it back to an index.
First match wins. StateStore permits an id to be registered more than once and resolves reads/writes to the latest such slot (see the duplicate- ParamID contract in StateStore::reset_triggers_rt), so under a duplicate id this returns a slot the store itself no longer reads. Preserved as-is because it is what every adapter's publication path has always done. RT-safe.
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 = [] {} ) |
|
inline |
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.
A writer advances the generation before it stores its value, so a snapshot is trusted only when no writer was in flight when it started and none had landed when it ended; a check at the end alone would accept a value read just before an in-flight writer stored its new one, and that parameter would later be reported to the host as a plugin-side change it never made. after_read runs between the read and the final check (tests use it to finish a writer there).
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 ) |
|
inline |
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.
This is the single implementation of the float-buffer bypass pass-through the AU v2/v3 and AAX adapters share; VST3 and CLAP keep their own inline loops because they additionally marshal f64 host buffers (see the per-format usage of LatencyCompensatedBypass above).
All-or-nothing across the block. Compensation is applied only when the boundary owns a dry-delay line for every output channel — a channel count above bypass.channel_capacity() falls back to a zero-delay copy for the whole block, degrading uniformly rather than mixing delayed and undelayed channels (matches the VST3/CLAP delayed gate). A zero reported latency collapses to a straight passthrough at no cost.
out_ptrs / in_ptrs are the per-channel float pointers (either may hold null entries — a null output channel is skipped, a null/absent input channel yields silence). count is the block frame count. RT-safe: no allocation, no lock (the delay lines were sized in bypass.prepare() off the audio thread).