Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::format::ProcessContext Struct Reference

Process context — passed every audio callback with transport state. More...

#include <process_context.hpp>

Public Member Functions

constexpr bool has_transport (TransportField field) const noexcept
bool is_realtime () const noexcept
bool is_offline () const noexcept
bool allows_offline_quality_work () const noexcept
bool should_reset_dsp_state () const noexcept
 True when DSP state should treat this block as a discontinuity boundary.
bool should_reset_stream_history () const noexcept
 True when continuous audio-stream history should be cleared.
bool is_maintenance_render () const noexcept
 True when this block is not a normal input-driven render but the host is still calling process() so a processor can settle internal state, drain a tail, or maintain bypass-aware state.
bool should_render_tail_only () const noexcept
 True when the host is asking the processor to render only existing tail state.

Public Attributes

double sample_rate = 0
int num_samples = 0
ProcessMode process_mode = ProcessMode::Realtime
 Runtime mode for this block.
bool is_bypassed = false
 True when the host is rendering the plugin's bypass path for this block.
bool is_tail_drain = false
 True when the host is asking a processor to continue rendering after input/transport stop so delay, reverb, or lookahead state can settle.
bool reset_requested = false
 True for the first block after a transport jump, seek, or explicit DSP reset boundary.
bool transport_jump = false
 True when the host observed a discontinuous timeline move since the previous block.
RenderSpeedHint render_speed_hint = RenderSpeedHint::Unknown
 Advisory render-speed category for hosts that know whether the current pass is live, faster-than-realtime export, or slower/constrained render.
bool is_playing = false
bool is_recording = false
double tempo_bpm = 120.0
double position_beats = 0.0
 Position in quarter notes.
int64_t position_samples = 0
int time_sig_numerator = 4
int time_sig_denominator = 4
int64_t bar = 0
 Bar index derived from position_beats + the active time signature.
bool is_looping = false
 True when the host's transport is in cycle/loop mode.
double loop_start_beats = 0.0
 Loop start in quarter notes, only meaningful when is_looping is true.
double loop_end_beats = 0.0
 Loop end in quarter notes, only meaningful when is_looping is true.
int64_t host_time_ns = 0
 Host clock timestamp matching the start of this block, in nanoseconds since an epoch the host chooses.
FrameRate frame_rate = FrameRate::unknown
 SMPTE frame rate when the host exposes one.
bool tempo_changed = false
 True when the host's reported tempo_bpm differs from the previous block.
bool time_sig_changed = false
 True when the host's reported time signature (time_sig_numerator or time_sig_denominator) differs from the previous block.
bool transport_changed = false
 True when any transport state field (is_playing, is_recording, is_looping) flipped since the previous block.
bool transport_started = false
 True on the first block of a run — the block where the host's transport begins rolling.
TransportValidity transport_validity {}
 Identifies which transport values were supplied for this block.
bool ordinary_loop_wrap = false
 True when the adapter classified this block's transport_jump as the expected backward move from a stable host loop end to its loop start.

Detailed Description

Process context — passed every audio callback with transport state.

Fields are populated by the host. Not all hosts provide all fields; when an adapter publishes transport_validity, it distinguishes unavailable values from valid defaults.

Adapter sourcing:

Change-flags (tempo_changed, time_sig_changed, transport_changed) are computed by the adapter once per block by diffing against the previous block's snapshot, so processors can branch on transitions only without re-reading every field.

Member Function Documentation

◆ allows_offline_quality_work()

bool pulp::format::ProcessContext::allows_offline_quality_work ( ) const
inlinenoexcept

◆ has_transport()

bool pulp::format::ProcessContext::has_transport ( TransportField field) const
inlineconstexprnoexcept

◆ is_maintenance_render()

bool pulp::format::ProcessContext::is_maintenance_render ( ) const
inlinenoexcept

True when this block is not a normal input-driven render but the host is still calling process() so a processor can settle internal state, drain a tail, or maintain bypass-aware state.

Processors must still obey the realtime/offline contract for the block.

◆ is_offline()

bool pulp::format::ProcessContext::is_offline ( ) const
inlinenoexcept

◆ is_realtime()

bool pulp::format::ProcessContext::is_realtime ( ) const
inlinenoexcept

◆ should_render_tail_only()

bool pulp::format::ProcessContext::should_render_tail_only ( ) const
inlinenoexcept

True when the host is asking the processor to render only existing tail state.

This is intentionally separate from bypass: some hosts bypass by short-circuiting process(), while others continue calling process() to let tails settle.

◆ should_reset_dsp_state()

bool pulp::format::ProcessContext::should_reset_dsp_state ( ) const
inlinenoexcept

True when DSP state should treat this block as a discontinuity boundary.

Hosts can request this explicitly, and adapters can derive it from a transport seek/jump. Processors commonly use this to clear synced phase, delay history, or tempo-grid caches before rendering the block.

◆ should_reset_stream_history()

bool pulp::format::ProcessContext::should_reset_stream_history ( ) const
inlinenoexcept

True when continuous audio-stream history should be cleared.

Unlike should_reset_dsp_state(), an ordinary host loop wrap is not destructive: audio is still arriving continuously, so clearing a delay line or WOLA overlap state would manufacture a gap at every cycle boundary. Explicit host resets always win, including when they coincide with a loop wrap.

Member Data Documentation

◆ bar

int64_t pulp::format::ProcessContext::bar = 0

Bar index derived from position_beats + the active time signature.

Hosts may already publish a precomputed bar (VST3 Vst::ProcessContext::barPositionMusic) — in that case the adapter uses the host value directly. Otherwise the adapter derives bar = floor(position_beats * (time_sig_denominator / 4) / time_sig_numerator) and writes it here so processors that just need "what bar am I in" do not recompute it per block. Default 0 matches a stopped-at-origin playhead.

◆ frame_rate

FrameRate pulp::format::ProcessContext::frame_rate = FrameRate::unknown

SMPTE frame rate when the host exposes one.

Default FrameRate::unknown is the documented sentinel meaning "host did not provide" — plugins must check before using.

◆ host_time_ns

int64_t pulp::format::ProcessContext::host_time_ns = 0

Host clock timestamp matching the start of this block, in nanoseconds since an epoch the host chooses.

Used for video sync against the OS clock. Sources: VST3 Vst::ProcessContext::systemTime (already nanoseconds on Apple; otherwise host-defined); AU mach_absolute_time() converted via mach_timebase_info (the AU adapter performs the conversion before writing here); CLAP has no host-time field today, so the adapter leaves the value at 0 (sentinel = "not provided"); AAX IACFTransport's sample-position only — host time is unavailable, so leave at 0.

◆ is_bypassed

bool pulp::format::ProcessContext::is_bypassed = false

True when the host is rendering the plugin's bypass path for this block.

Most current adapters short-circuit before calling process() while bypassed, so the default remains false and this flag is only meaningful on hosts that intentionally process while bypassed to drain tails.

◆ is_looping

bool pulp::format::ProcessContext::is_looping = false

True when the host's transport is in cycle/loop mode.

VST3 exposes this as the kCycleActive flag on ProcessContext; AU surfaces it via HostTransport's outIsCycling; CLAP via the CLAP_TRANSPORT_IS_LOOP_ACTIVE bit on clap_event_transport::flags; AAX via IACFTransport's loop state. Default false (no loop).

◆ is_playing

bool pulp::format::ProcessContext::is_playing = false

◆ is_recording

bool pulp::format::ProcessContext::is_recording = false

◆ is_tail_drain

bool pulp::format::ProcessContext::is_tail_drain = false

True when the host is asking a processor to continue rendering after input/transport stop so delay, reverb, or lookahead state can settle.

◆ loop_end_beats

double pulp::format::ProcessContext::loop_end_beats = 0.0

Loop end in quarter notes, only meaningful when is_looping is true.

Same source list as loop_start_beats. Default 0 (loop_start == loop_end => no loop range yet).

◆ loop_start_beats

double pulp::format::ProcessContext::loop_start_beats = 0.0

Loop start in quarter notes, only meaningful when is_looping is true.

Mirrors position_beats's PPQ convention. Sources: VST3 Vst::ProcessContext::cycleStartMusic; AU HostTransport::outCycleStartBeat; CLAP clap_event_transport::loop_start_beats (converted from CLAP's fixed-point clap_beattime); AAX IACFTransport::GetCurrentLoopPosition. Default 0.

◆ num_samples

int pulp::format::ProcessContext::num_samples = 0

◆ ordinary_loop_wrap

bool pulp::format::ProcessContext::ordinary_loop_wrap = false

True when the adapter classified this block's transport_jump as the expected backward move from a stable host loop end to its loop start.

transport_jump deliberately remains true: timeline-driven processors still need to observe that discontinuity. Streaming effects can use this narrower signal to preserve delay, overlap-add, and reverb history across an ordinary cycle while continuing to clear it on a real seek.

Classification is conservative. It is only true when the host supplied a coherent loop range plus enough beat/tempo timing to predict the wrapped position. Missing or inconsistent metadata leaves it false.

◆ position_beats

double pulp::format::ProcessContext::position_beats = 0.0

Position in quarter notes.

◆ position_samples

int64_t pulp::format::ProcessContext::position_samples = 0

◆ process_mode

ProcessMode pulp::format::ProcessContext::process_mode = ProcessMode::Realtime

Runtime mode for this block.

Defaults to live realtime processing for source compatibility; offline/headless/render hosts should set ProcessMode::Offline explicitly.

◆ render_speed_hint

RenderSpeedHint pulp::format::ProcessContext::render_speed_hint = RenderSpeedHint::Unknown

Advisory render-speed category for hosts that know whether the current pass is live, faster-than-realtime export, or slower/constrained render.

◆ reset_requested

bool pulp::format::ProcessContext::reset_requested = false

True for the first block after a transport jump, seek, or explicit DSP reset boundary.

Processors can use this to clear tempo-synced phase or delay history without guessing from position discontinuities.

◆ sample_rate

double pulp::format::ProcessContext::sample_rate = 0

◆ tempo_bpm

double pulp::format::ProcessContext::tempo_bpm = 120.0

◆ tempo_changed

bool pulp::format::ProcessContext::tempo_changed = false

True when the host's reported tempo_bpm differs from the previous block.

Lets processors recompute tempo-dependent derived state (sample-domain envelope rates, delay-line beat lengths) only on transitions instead of every block. Computed by the adapter as current.tempo_bpm != previous.tempo_bpm. Default false (no change relative to a hypothetical previous block, which matches the initial-state contract).

◆ time_sig_changed

bool pulp::format::ProcessContext::time_sig_changed = false

True when the host's reported time signature (time_sig_numerator or time_sig_denominator) differs from the previous block.

Lets processors rebuild bar-grid state on transitions only. Default false.

◆ time_sig_denominator

int pulp::format::ProcessContext::time_sig_denominator = 4

◆ time_sig_numerator

int pulp::format::ProcessContext::time_sig_numerator = 4

◆ transport_changed

bool pulp::format::ProcessContext::transport_changed = false

True when any transport state field (is_playing, is_recording, is_looping) flipped since the previous block.

Lets processors reset playback-only DSP state (e.g. flush a reverb tail when transport stops) on transitions only. Default false.

◆ transport_jump

bool pulp::format::ProcessContext::transport_jump = false

True when the host observed a discontinuous timeline move since the previous block.

This is narrower than transport_changed: play/stop transitions do not imply a jump unless position also changed discontinuously.

◆ transport_started

bool pulp::format::ProcessContext::transport_started = false

True on the first block of a run — the block where the host's transport begins rolling.

Set when is_playing goes false→true, and also on the very first block a processor ever sees if the transport is already playing (a plugin inserted mid-playback), because that block starts a run from the processor's point of view.

This is deliberately NOT folded into should_reset_dsp_state(). A transport start is not a timeline discontinuity: pressing play at a parked position leaves position_samples unchanged, so transport_jump stays false and delay/reverb tails must survive. What a transport start does invalidate is run-relative phase — a tempo-synced LFO's cycle origin, a clock generator's first-pulse delay, a step sequencer's step index.

Processors that free-run a phase accumulator across a stop and then "catch up" to the new position on the next play emit a burst of backlogged events on that block. Capture your run origin here instead. Prefer deriving event positions from position_beats outright; then a start, a seek, and a loop wrap are all the same case and none of them can produce a burst.

◆ transport_validity

TransportValidity pulp::format::ProcessContext::transport_validity {}

Identifies which transport values were supplied for this block.

A clear bit means the corresponding value is only its compatibility default. Format adapters publish this mask from their host APIs; a host that does not supply transport leaves it empty. Kept after the original data members so existing field offsets do not move.


The documentation for this struct was generated from the following file: