Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
baked_graph_processor.hpp
Go to the documentation of this file.
1#pragma once
2
3// Lowering a fixed SignalGraph into a single shippable Processor.
4//
5// `bake()` freezes a prepared, fully-lowerable SignalGraph into one
6// BakedGraphProcessor: a self-contained pulp::format::Processor that drives a
7// frozen plan through the SAME canonical GraphRuntimeExecutor::process_routed()
8// the live graph uses, so its output is bit-identical to the live graph's walk
9// for the lowerable subset. There is no codegen and no second routing backend —
10// the baked Processor only CALLS process_routed, never defines it.
11//
12// Lowerable: AudioInput, AudioOutput, the built-in Gain utility, and a Custom
13// node whose registered type opts in with `lowerable = true`, matches the node's
14// port shape, and is transport-independent (the baked process() drops the host
15// transport, so a transport-sensitive node would diverge).
16// A graph is REFUSED loudly (null processor + a reason) rather than silently
17// mis-baked when it is not prepared, not executor-eligible, or carries a hosted
18// Plugin node (opaque external state, not self-contained).
19// A plan can be kept in memory (bake) or serialized to a signed .pulpbake
20// envelope and read back (bake_to_plan -> write_baked_signed -> load_baked); see
21// baked_codec.hpp for the on-disk format and its trust gate.
22//
23// bake() captures the graph's TOPOLOGY and Gain VALUES, not hot runtime state: the
24// baked Processor builds fresh feedback/delay/scratch state in prepare() and starts
25// it from zero. If the source graph has already processed blocks (non-zero feedback
26// history), that history is not cloned — the baked Processor begins a fresh stream.
27
34
35#include <atomic>
36#include <cstddef>
37#include <cstdint>
38#include <functional>
39#include <memory>
40#include <span>
41#include <string>
42#include <type_traits>
43#include <unordered_map>
44#include <utility>
45#include <vector>
46
47namespace pulp::host {
48
49namespace detail {
50// Per-node injection substrate; full definitions live in the .cpp so this
51// widely-included header stays free of param_cursor/store.
52struct BakedParamMailbox;
53struct BakedParamNodeState;
54struct BakedCustomNodeRuntime;
55struct BakedSampleRegionRuntime;
56} // namespace detail
57
58// Bake-layer parameter-injection binding captured at bake() for one param-
59// declaring custom node: the bound param-aware process callback (instance
60// keepalive captured) plus the node's declared params. Handed to the
61// BakedGraphProcessor so it can size the node's mailbox + build its cursor.
64 std::vector<CustomNodeBakedParam> params;
65};
66
67// Why a graph could not be lowered into a self-contained BakedGraphProcessor.
70 NotPrepared, // graph.prepare() has not published a snapshot
71 NotExecutorEligible, // outside the routed executor's bit-exact subset
72 HostedPluginNotSelfContained, // a Plugin node carries opaque external state
73 CustomNotYetLowerable, // a Custom node is unresolved, has no lowering yet,
74 // or its shape does not match its registered type
75 CustomNotLowerable, // a Custom type is not opted into baking (lowerable=false)
76 CustomTransportNotLowerable, // a transport-sensitive Custom node (baked process
77 // drops the transport, so it would diverge)
78 NonAudioLaneNotLowerable, // a MIDI node, or a MIDI/automation/sidechain edge
79 CodecRejected, // load_baked: the .pulpbake bytes failed the signed
80 // envelope (bad magic/length/manifest/trust/signature/
81 // hash) or the bounded plan parse
82 StatefulCustomNotYetLoadable, // load_baked: matching Custom instance could
83 // not be created or rejected authenticated state.
84 ParameterContractMismatch, // promoted parameter identities or metadata are invalid
86};
87
88// Result of bake(): on success `processor` is non-null and `accepted` is true;
89// on refusal `processor` is null, `accepted` is false, and `reason` /
90// `offending_node` / `message` explain the refusal loudly.
92 std::unique_ptr<pulp::format::Processor> processor;
93 bool accepted = false;
96 std::string message;
97};
98
99// Proof that a graph topology is lowerable into a self-contained baked Processor.
100// The single gate both bake() and (later) the on-disk load path consult, so the
101// trusted and untrusted paths can never diverge on what is bakeable. accepted==true
102// means every node kind is bakeable (audio I/O + Gain; Plugin/Custom/MIDI refused
103// with a specific reason), every connection is plain audio, and the topology is
104// executor-eligible. Pure — no allocation, no graph state. bake() calls it after
105// its is_prepared() precondition.
112
113// `resolve_custom`, when set, resolves a Custom node's registered type (by
114// custom_type_id + custom_type_version) so the gate can accept a lowerable,
115// shape-matched, non-transport-sensitive Custom node. When empty (the default) any
116// Custom node is refused as CustomNotYetLowerable — the in-process bake path passes
117// a resolver over the graph's registry; a caller with no registry omits it.
119 std::span<const GraphNode> nodes,
120 std::span<const Connection> connections,
121 const std::function<const CustomNodeType*(std::string_view type_id, int version)>&
122 resolve_custom = {});
123
124// Per-Custom-node lifecycle hooks captured at bake() from the node's registered
125// type + live instance. prepare() runs them (control thread) so a re-prepare is a
126// real re-init boundary: the instance is re-prepared at the HOST's actual
127// rate/block (not whatever the source graph — or load_baked's nominal
128// 48k/512 — last used) and its DSP state is reset, honoring the "starts a
129// fresh stream" contract above. Either fn may be empty (type registered no
130// such hook); each closure holds the instance shared_ptr, so it is also a
131// keepalive.
133 std::function<void(double sample_rate, int max_block)> prepare;
134 std::function<void()> reset;
135 // Present only for a processor reconstructed from a signed artifact carrying
136 // initial Custom state. Runs after prepare/reset so those hooks cannot erase
137 // the authenticated state. False leaves the processor unprepared.
138 std::function<bool()> restore_state;
139};
140
141// Complete bake-time binding for one Custom node. Keeping process, lifecycle,
142// parameter support, and latency under one NodeId-keyed record prevents the
143// four parallel maps from drifting as Custom-node capabilities evolve.
150
151// Outcome of a ParamInjector::inject() call. Distinguishes the two failure
152// modes the old bool return conflated: a dead handle (never call inject() on an
153// invalid() injector) versus a source queue that overflowed before it reached
154// us (the retained prefix is still published — a real, usable partial success).
155enum class InjectStatus {
156 Ok, // published in full
157 PartialOverflow, // queue path: the source queue overflowed; its retained
158 // prefix is published. Single path: the pending batch was
159 // full of other params' events; this event was dropped.
160 InvalidHandle, // this injector holds no live claim (valid() == false); nothing published
161};
162
163// Exclusive control-side handle for injecting parameters into ONE baked custom
164// node. Obtain from BakedGraphProcessor::claim_param_injection(); move-only;
165// releases the node's exclusive claim on destruction. inject() is RT-safe and
166// allocation-free — it publishes into the node's single-writer mailbox, which
167// the baked process() drains on its next block. Publication semantics:
168// inject(queue) REPLACES the pending batch (latest-published-queue wins, like
169// the live mailbox); inject(single) ACCUMULATES — the new event merges into
170// the still-unconsumed pending batch, superseding only that param's pending
171// entries, so N single injects to different params on one node between blocks
172// ALL land (they do not collapse to the last one). WITHIN a batch events are
173// sample-accurate and may ramp (ParamCursor over sample_offset +
174// ramp_duration_sample_frames), and a ramp longer than one block continues to
175// completion across subsequent blocks. Exactly one injector may hold a node at
176// a time (two owners injecting into one node is the hazard this claim prevents).
178public:
179 ParamInjector() noexcept = default;
181 ParamInjector(ParamInjector&& other) noexcept;
182 ParamInjector& operator=(ParamInjector&& other) noexcept;
183 ParamInjector(const ParamInjector&) = delete;
184 ParamInjector& operator=(const ParamInjector&) = delete;
185
186 // True iff this handle holds a live exclusive claim on a node's mailbox.
187 bool valid() const noexcept { return mailbox_ != nullptr; }
188
189 // Publish a whole queue of sample-accurate events (the general path).
190 // Returns InvalidHandle iff !valid() (nothing published — this is a caller
191 // error, inject() is meant to be called only on a valid() handle), or
192 // PartialOverflow when `events` already reports source-side overflow (the
193 // retained prefix is still published — a usable partial success), otherwise
194 // Ok. RT-safe / allocation-free.
196 // Convenience: publish a single immediate (ramp_duration==0) or ramped
197 // event. Accumulates: merges into the pending (not-yet-consumed) batch,
198 // superseding only THIS param's pending entries — consecutive single
199 // injects to different params between blocks all apply. Returns
200 // PartialOverflow only in the pathological case where the pending batch is
201 // already full of OTHER params' events (a full-capacity queue publish, not
202 // yet consumed): the pending batch stays published unchanged and this
203 // event is dropped. Otherwise Ok / InvalidHandle.
205
206private:
208 explicit ParamInjector(std::shared_ptr<detail::BakedParamMailbox> mailbox) noexcept;
209 void release() noexcept;
210 std::shared_ptr<detail::BakedParamMailbox> mailbox_;
211};
212
213// A SignalGraph frozen into a shippable Processor. Owns the reconstructed plan
214// (nodes + connections), its own heap-stable Gain atomics, and the canonical
215// executor's serialized routing snapshot + scratch pool. process() bridges the
216// host's main in/out buffers into a ProcessBlock and runs the frozen plan via
217// GraphRuntimeExecutor::process_routed(). It must NOT define process_routed /
218// process_parallel (single-backend invariant) — only call them.
219//
220// In-place hosts: process() supports input and output views over the SAME
221// memory (Logic-style aliased buffers). process_routed zeroes the main output
222// bus before gathering AudioInput, which would destroy an aliased input — so
223// process() detects overlap and reads the input from a prepare()-sized scratch
224// copy instead (audio thread does only the memcpy; no allocation).
226public:
227 BakedGraphProcessor(std::vector<GraphNode> nodes,
228 std::vector<Connection> connections,
229 int input_channels,
230 int output_channels,
231 std::string name,
232 std::string bundle_id,
233 // One complete binding per Custom node, consolidating
234 // what were four parallel NodeId-keyed maps (process
235 // callback, intrinsic latency, lifecycle hooks, and
236 // bake-layer param injection) into a single record that
237 // cannot fall out of step across them. Callback copies
238 // capture their instance keepalive, so the baked
239 // Processor owns all required runtime state and holds no
240 // reference back into the source graph.
241 std::unordered_map<NodeId, BakedCustomNodeBinding>
242 custom_nodes = {});
243 // Validate and freeze promoted metadata before a Processor can be returned
244 // to an adapter. Invalid contracts return ParameterContractMismatch with no
245 // processor; this does not replace the graph's topology/lowering proof.
246 static LowerResult
247 create_with_sample_regions(std::vector<GraphNode> nodes, std::vector<Connection> connections,
248 int input_channels, int output_channels, std::string name,
249 std::string bundle_id,
250 std::unordered_map<NodeId, BakedCustomNodeBinding> custom_nodes,
251 std::vector<SampleRegionDefinition> sample_regions);
252
253 // Own exact scalar descriptors independently of the source graph registry.
254 static LowerResult
255 create_with_sample_regions(std::vector<GraphNode> nodes, std::vector<Connection> connections,
256 int input_channels, int output_channels, std::string name,
257 std::string bundle_id,
258 std::unordered_map<NodeId, BakedCustomNodeBinding> custom_nodes,
259 std::vector<SampleRegionDefinition> sample_regions,
260 std::vector<SampleKernelDescriptor> sample_kernels);
261
263
265 int latency_samples() const override {
266 return prepared_latency_samples_.load(std::memory_order_relaxed);
267 }
270 return sample_region_parameter_contract_;
271 }
273 return sample_region_parameter_binding_.get();
274 }
275 void prepare(const pulp::format::PrepareContext& context) override;
277 const pulp::audio::BufferView<const float>& audio_input,
278 pulp::midi::MidiBuffer& midi_in,
279 pulp::midi::MidiBuffer& midi_out,
280 const pulp::format::ProcessContext& context) override;
281
282 // Claim exclusive parameter-injection rights for a baked custom node. Returns
283 // a valid ParamInjector iff `node` is a param-declaring baked custom node AND
284 // no injector currently holds it; otherwise returns an invalid handle. The
285 // returned handle survives prepare()/re-prepare (the mailbox persists across
286 // both). Control thread only.
288
289private:
290 BakedGraphProcessor(std::vector<GraphNode> nodes, std::vector<Connection> connections,
291 int input_channels, int output_channels, std::string name,
292 std::string bundle_id,
293 std::unordered_map<NodeId, BakedCustomNodeBinding> custom_nodes,
294 SampleRegionParameterContract parameter_contract);
295
296 // Build per-node injection state and install the draining wrapper into each
297 // param-declaring Custom runtime. Called by prepare()
298 // before the executor snapshot is built; off the audio thread.
299 void prepare_param_injection();
300
301 // The frozen plan, captured at bake() time and owned for the Processor's
302 // lifetime. Gain values ride GraphNode::gain; prepare() seeds the atomics.
303 std::vector<GraphNode> nodes_;
304 std::vector<Connection> conns_;
305
306 // Heap-stable per-Gain-node atomics (one unique_ptr each) so the routed Gain
307 // binding's user_data pointer survives gains_ growth. Built in prepare().
308 std::vector<std::unique_ptr<std::atomic<float>>> gains_;
309 std::unordered_map<NodeId, std::size_t> gain_index_;
310
311 // Canonical executor + the serialized fused plan it runs. The snapshot and
312 // pool are sized once in prepare() (off the audio thread); process() only
313 // calls process_routed, which is allocation-free for a fitting pool.
317 // Empty for this slice's lowerable subset (no Plugin nodes), but the
318 // snapshot builder requires the storage to exist.
319 std::vector<PluginBindingContext> plugin_ctx_;
320 PluginRoutingScratch plugin_scratch_;
321 // One owned runtime record per Custom node, consolidating its process,
322 // lifecycle, parameter injection, mailbox/state, and latency callback. Each
323 // record holds its own instance keepalive. Empty for a custom-free graph;
324 // prepare() binds custom_ctx_ from these records.
325 std::unordered_map<NodeId, std::unique_ptr<detail::BakedCustomNodeRuntime>> custom_nodes_;
326 std::vector<CustomBindingContext> custom_ctx_;
327
328 // In-place-host guard scratch: when the host's input channels alias its
329 // output channels, process() copies the input here BEFORE process_routed
330 // zeroes the output bus. Sized in prepare() (input_channels_ × max block);
331 // the audio thread only detects overlap and memcpys — no allocation.
332 std::vector<float> input_alias_scratch_;
333 std::vector<float*> input_alias_ptrs_;
334
335 std::string name_;
336 std::string bundle_id_;
337 SampleRegionParameterContract sample_region_parameter_contract_;
338 std::unique_ptr<SampleRegionParameterBinding> sample_region_parameter_binding_;
339 std::unique_ptr<detail::BakedSampleRegionRuntime> sample_region_runtime_;
340 int input_channels_ = 2;
341 int output_channels_ = 2;
342 int prepared_max_block_ = 0;
343 // Resolved at prepare(), not at construction: a Custom node's intrinsic
344 // latency is a function of the sample rate, which is not known until then.
345 std::atomic<int> prepared_latency_samples_{0};
346 bool prepared_ = false;
347};
348
349// Lower a prepared, fully-lowerable SignalGraph into a BakedGraphProcessor.
350// Returns LowerResult{accepted=true, processor=...} on success, or a loud
351// refusal (processor=nullptr) with a reason for any non-lowerable graph.
353
354// Verify + load a signed .pulpbake artifact into a BakedGraphProcessor. `trust` is
355// the set of accepted signer keys; `custom_types` are the host's registered custom
356// node types (a Custom record's process code is re-resolved from these, never from
357// the file). The bytes go through verify_and_extract_plan (signature-before-parse),
358// then the plan is rebuilt into a SignalGraph and run through bake() — so bake()'s
359// full lowerability re-proof applies to the reconstructed topology; the file's
360// implicit claim is never trusted. Returns CodecRejected if the envelope/parse fails,
361// or bake()'s refusal reason if the reconstructed graph is not lowerable. v1 supports
362// stateful custom nodes when the matching registered type supplies create +
363// load_state. The authenticated blob is restored after each host prepare/reset;
364// malformed state fails closed before a processor is returned.
365LowerResult load_baked(std::span<const std::uint8_t> bytes, const BakedTrust& trust,
366 const std::vector<CustomNodeType>& custom_types);
367
368// Exact block/scalar registration pair used by the bake-v2 preflight. This is
369// deliberately separate from CustomNodeType so v1 callers retain the original
370// source surface and a v2 artifact can never resolve sample code by block type
371// identity alone. Every supplied pair must be valid; an identity used only
372// by residual Custom nodes resolves through its block registration internally.
377
378// Named, non-default wrapper keeps the paired overload distinct from legacy
379// calls such as load_baked(bytes, trust, {}).
381 public:
383 static BakedTypeRegistry from(std::vector<BakedTypeRegistration> registrations) {
384 return BakedTypeRegistry(std::move(registrations), ConstructionKey{});
385 }
386
387 const std::vector<BakedTypeRegistration>& registrations() const noexcept {
388 return registrations_;
389 }
390
391 private:
392 struct ConstructionKey {};
393 BakedTypeRegistry(std::vector<BakedTypeRegistration> registrations, ConstructionKey)
394 : registrations_(std::move(registrations)) {}
395
396 std::vector<BakedTypeRegistration> registrations_;
397};
398
399// Verify a signed v2 artifact, reconstruct its authored topology and region
400// metadata in an isolated PreparedTopologyEdit, and re-run exact region and
401// ordinary graph proofs. Inspection returns the callback-free verified plan;
402// it does not publish or execute a runtime snapshot.
411
412BakedPlanLoadResult load_baked_plan(std::span<const std::uint8_t> bytes, const BakedTrust& trust,
413 const std::vector<BakedTypeRegistration>& registrations);
414
415namespace detail {
416LowerResult load_baked_registered(std::span<const std::uint8_t> bytes, const BakedTrust& trust,
417 const BakedTypeRegistry& registry);
418}
419
420// Paired registrations admit executable signed sample regions with private
421// scalar state. Built-in kernels need no extra registrations. Call
422// define_parameters(store) before prepare(), including for an empty manifest;
423// the adapter store must outlive the processor. An empty brace argument still
424// selects the legacy v1-only vector overload. Residual Custom callbacks own
425// their block instances and authenticated state; a failed opaque state restore
426// on reprepare retains the legacy fail-silent behavior, not region-bank rollback.
427template <typename Registry>
428 requires std::is_same_v<std::remove_cvref_t<Registry>, BakedTypeRegistry>
429LowerResult load_baked(std::span<const std::uint8_t> bytes, const BakedTrust& trust,
430 Registry&& registry) {
431 return detail::load_baked_registered(bytes, trust, registry);
432}
433
434// Result of bake_to_plan(): `plan` is set iff `accepted`; on refusal the reason /
435// offending_node / message explain why (mirrors bake()'s LowerResult so the write
436// front door can report a non-shippable graph as precisely as the in-memory path).
438 std::optional<BakedPlan> plan;
439 bool accepted = false;
442 std::string message;
443};
444
445// Extract a serializable BakedPlan from a prepared, lowerable graph — the write-path
446// front door: bake_to_plan(graph).plan -> write_baked_signed(*plan, key) -> bytes.
447// Refuses (accepted=false, plan=nullopt) with a reason if the graph is not prepared
448// or not lowerable (same proof as bake()). Custom state is the authored blob last
449// supplied through set_custom_node_state(), not a live save_state() snapshot: a
450// prepared graph may be processing concurrently and save_state has no RT concurrency
451// contract.
453
454} // namespace pulp::host
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
Pre-allocated scratch buffers backing the routing process() path.
Definition graph_runtime_executor.hpp:297
Definition graph_runtime_executor.hpp:738
Control-thread-built graph snapshot for GraphRuntimeExecutor.
Definition graph_runtime_executor.hpp:159
Processor()
Definition processor.hpp:176
BakedGraphProcessor(std::vector< GraphNode > nodes, std::vector< Connection > connections, int input_channels, int output_channels, std::string name, std::string bundle_id, std::unordered_map< NodeId, BakedCustomNodeBinding > custom_nodes={})
void define_parameters(pulp::state::StateStore &store) override
Register parameters with the state store.
pulp::format::PluginDescriptor descriptor() const override
Return the plugin's metadata. Called once during initialization.
const SampleRegionParameterContract & sample_region_parameter_contract() const noexcept
Definition baked_graph_processor.hpp:269
const SampleRegionParameterBinding * sample_region_parameter_binding() const noexcept
Definition baked_graph_processor.hpp:272
void prepare(const pulp::format::PrepareContext &context) override
Prepare for processing.
static LowerResult create_with_sample_regions(std::vector< GraphNode > nodes, std::vector< Connection > connections, int input_channels, int output_channels, std::string name, std::string bundle_id, std::unordered_map< NodeId, BakedCustomNodeBinding > custom_nodes, std::vector< SampleRegionDefinition > sample_regions, std::vector< SampleKernelDescriptor > sample_kernels)
int latency_samples() const override
Latency in samples introduced by this processor (default 0).
Definition baked_graph_processor.hpp:265
ParamInjector claim_param_injection(NodeId node) noexcept
static LowerResult create_with_sample_regions(std::vector< GraphNode > nodes, std::vector< Connection > connections, int input_channels, int output_channels, std::string name, std::string bundle_id, std::unordered_map< NodeId, BakedCustomNodeBinding > custom_nodes, std::vector< SampleRegionDefinition > sample_regions)
void process(pulp::audio::BufferView< float > &audio_output, const pulp::audio::BufferView< const float > &audio_input, pulp::midi::MidiBuffer &midi_in, pulp::midi::MidiBuffer &midi_out, const pulp::format::ProcessContext &context) override
Process one buffer of audio.
Definition baked_graph_processor.hpp:380
const std::vector< BakedTypeRegistration > & registrations() const noexcept
Definition baked_graph_processor.hpp:387
static BakedTypeRegistry from(std::vector< BakedTypeRegistration > registrations)
Definition baked_graph_processor.hpp:383
Definition baked_graph_processor.hpp:177
InjectStatus inject(const state::ParameterEvent &event) noexcept
bool valid() const noexcept
Definition baked_graph_processor.hpp:187
InjectStatus inject(const state::ParameterEventQueue &events) noexcept
friend class BakedGraphProcessor
Definition baked_graph_processor.hpp:207
ParamInjector() noexcept=default
Definition sample_region_parameters.hpp:80
Definition sample_region_parameters.hpp:28
Definition signal_graph_runtime.hpp:83
Collection of timestamped MIDI events within a single audio buffer period.
Definition buffer.hpp:31
Definition parameter_event_queue.hpp:82
Centralized parameter storage with lock-free value access.
Definition store.hpp:164
Definition child_process_manager.hpp:18
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
Definition graph_runtime_buffer_assignment.hpp:8
std::uint32_t NodeId
Definition graph_types.hpp:7
Definition baked_codec.hpp:158
LowerResult load_baked_registered(std::span< const std::uint8_t > bytes, const BakedTrust &trust, const BakedTypeRegistry &registry)
Bounded event contracts shared by host ingress and graph-authored nodes.
Definition anticipation_eligibility.hpp:9
@ None
Definition anticipation_eligibility.hpp:22
BakedPlanLoadResult load_baked_plan(std::span< const std::uint8_t > bytes, const BakedTrust &trust, const std::vector< BakedTypeRegistration > &registrations)
LowerResult load_baked(std::span< const std::uint8_t > bytes, const BakedTrust &trust, const std::vector< CustomNodeType > &custom_types)
LowerResult bake(const SignalGraph &graph)
std::function< void(audio::BufferView< float > &output, const audio::BufferView< const float > &input, int num_samples, const BakedParamView &params)> CustomNodeParamProcessFn
Definition custom_node_type.hpp:61
LowerRejectReason
Definition baked_graph_processor.hpp:68
@ NonAudioLaneNotLowerable
Definition baked_graph_processor.hpp:78
@ NotPrepared
Definition baked_graph_processor.hpp:70
@ None
Definition baked_graph_processor.hpp:69
@ CustomTransportNotLowerable
Definition baked_graph_processor.hpp:76
@ HostedPluginNotSelfContained
Definition baked_graph_processor.hpp:72
@ NotExecutorEligible
Definition baked_graph_processor.hpp:71
@ ParameterContractMismatch
Definition baked_graph_processor.hpp:84
@ CustomNotYetLowerable
Definition baked_graph_processor.hpp:73
@ CodecRejected
Definition baked_graph_processor.hpp:79
@ StatefulCustomNotYetLoadable
Definition baked_graph_processor.hpp:82
@ CustomNotLowerable
Definition baked_graph_processor.hpp:75
@ SpectralPersistenceUnsupported
Definition baked_graph_processor.hpp:85
LowerabilityProof lowerability_of(std::span< const GraphNode > nodes, std::span< const Connection > connections, const std::function< const CustomNodeType *(std::string_view type_id, int version)> &resolve_custom={})
std::function< void(audio::BufferView< float > &output, const audio::BufferView< const float > &input, int num_samples)> CustomNodeProcessFn
Definition custom_node_type.hpp:24
BakePlanResult bake_to_plan(const SignalGraph &graph)
std::uint32_t SampleRegionId
Definition sample_region_proof.hpp:13
InjectStatus
Definition baked_graph_processor.hpp:155
@ InvalidHandle
Definition baked_graph_processor.hpp:160
@ PartialOverflow
Definition baked_graph_processor.hpp:157
@ Ok
Definition baked_graph_processor.hpp:156
Definition analyzer_provider.hpp:12
STL namespace.
Plugin metadata — declared once, immutable.
Definition plugin_descriptor.hpp:245
Definition prepare_resources.hpp:102
Process context — passed every audio callback with transport state.
Definition process_context.hpp:89
Definition baked_graph_processor.hpp:437
NodeId offending_node
Definition baked_graph_processor.hpp:441
bool accepted
Definition baked_graph_processor.hpp:439
LowerRejectReason reason
Definition baked_graph_processor.hpp:440
std::string message
Definition baked_graph_processor.hpp:442
std::optional< BakedPlan > plan
Definition baked_graph_processor.hpp:438
Definition baked_graph_processor.hpp:144
std::function< int(double)> latency_samples
Definition baked_graph_processor.hpp:148
CustomNodeLifecycle lifecycle
Definition baked_graph_processor.hpp:146
BakedCustomParamBinding params
Definition baked_graph_processor.hpp:147
CustomNodeProcessFn process
Definition baked_graph_processor.hpp:145
Definition baked_graph_processor.hpp:62
CustomNodeParamProcessFn process
Definition baked_graph_processor.hpp:63
std::vector< CustomNodeBakedParam > params
Definition baked_graph_processor.hpp:64
Definition baked_graph_processor.hpp:403
SampleRegionId offending_region
Definition baked_graph_processor.hpp:407
std::optional< BakedPlan > plan
Definition baked_graph_processor.hpp:404
bool accepted
Definition baked_graph_processor.hpp:405
NodeId offending_node
Definition baked_graph_processor.hpp:408
std::string message
Definition baked_graph_processor.hpp:409
LowerRejectReason reason
Definition baked_graph_processor.hpp:406
Definition baked_codec.hpp:188
Definition baked_graph_processor.hpp:373
SampleKernelDescriptor sample
Definition baked_graph_processor.hpp:375
CustomNodeType block
Definition baked_graph_processor.hpp:374
Definition baked_graph_processor.hpp:132
std::function< void(double sample_rate, int max_block)> prepare
Definition baked_graph_processor.hpp:133
std::function< bool()> restore_state
Definition baked_graph_processor.hpp:138
std::function< void()> reset
Definition baked_graph_processor.hpp:134
Definition custom_node_type.hpp:90
Definition baked_graph_processor.hpp:91
bool accepted
Definition baked_graph_processor.hpp:93
std::string message
Definition baked_graph_processor.hpp:96
LowerRejectReason reason
Definition baked_graph_processor.hpp:94
NodeId offending_node
Definition baked_graph_processor.hpp:95
std::unique_ptr< pulp::format::Processor > processor
Definition baked_graph_processor.hpp:92
Definition baked_graph_processor.hpp:106
NodeId offending_node
Definition baked_graph_processor.hpp:108
LowerRejectReason reason
Definition baked_graph_processor.hpp:109
bool accepted
Definition baked_graph_processor.hpp:107
std::string message
Definition baked_graph_processor.hpp:110
Definition signal_graph_executor_routing.hpp:38
Definition custom_node_type.hpp:386
Definition parameter_event_queue.hpp:34