pub struct Graph { /* private fields */ }Expand description
A real-time-safe directed acyclic graph of audio nodes.
A Graph moves through three phases:
- Build — call
Graph::add_nodeto register nodes andGraph::linkto wire output ports to input ports. - Compile — call
Graph::compilewith aGraphConfig. This runs the topological sort, rejects cycles, and pre-allocates every scratch frame. - Run — call
Graph::process_cycleonce per audio cycle on the RT thread. UseGraph::feedto seed external inputs before a cycle andGraph::read_output/Graph::read_inputto tap results after.
See the crate-level documentation for the real-time safety contract.
Implementations§
Source§impl Graph
impl Graph
Sourcepub fn add_node(&mut self, node: Box<dyn AudioNode>) -> NodeId
pub fn add_node(&mut self, node: Box<dyn AudioNode>) -> NodeId
Adds a node to the graph and returns its stable NodeId.
The returned id equals the node’s index in insertion order and never
changes for the lifetime of the graph. Scratch frames for the node’s
ports are allocated later in Graph::compile.
Sourcepub fn link(
&mut self,
from: (NodeId, PortIdx),
to: (NodeId, PortIdx),
) -> Result<LinkId, GraphError>
pub fn link( &mut self, from: (NodeId, PortIdx), to: (NodeId, PortIdx), ) -> Result<LinkId, GraphError>
Links an output port to an input port, validating both endpoints and their compatibility.
The from port must be an output and the to port an input;
their channel counts and sample formats must match. The edge is stored
but the graph is not recompiled — call Graph::compile (or design
the full topology before compiling) before processing.
§Errors
Returns GraphError::NodeNotFound if either node does not exist,
GraphError::PortNotFound if a port index is out of range,
GraphError::PortDirectionMismatch if the directions are wrong, or
GraphError::PortIncompatible if channel/format differ.
Sourcepub fn compile(&mut self, config: GraphConfig) -> Result<(), GraphError>
pub fn compile(&mut self, config: GraphConfig) -> Result<(), GraphError>
Compiles the graph: topologically sorts the nodes and pre-allocates every scratch frame.
This is the only place allocation is permitted. After compile
succeeds, Graph::process_cycle is guaranteed to be allocation-free.
§Errors
Returns GraphError::AlreadyCompiled if called twice, or
GraphError::CycleDetected if the topology contains a cycle.
Sourcepub fn process_cycle(
&mut self,
ctx: &mut ProcessContext,
) -> Result<(), GraphError>
pub fn process_cycle( &mut self, ctx: &mut ProcessContext, ) -> Result<(), GraphError>
Processes one audio cycle on the real-time thread.
For each node in dependency order this copies connected upstream outputs
into the node’s input scratch (or zeroes unconnected inputs), then
invokes the node’s
process. The whole pass is bounded
and allocation-free: every slice is pre-sized by Graph::compile and
only bounded for loops / slice copies are used.
§Real-time safety
This method performs no allocation, locking, panicking, or system
call. The single Err(NotCompiled) return on the uncompiled path is a
stack-only branch (the variant carries no heap data); on the happy path
the method returns Ok(()).
§Errors
Returns GraphError::NotCompiled if Graph::compile has not been
called.
Sourcepub fn feed(&mut self, node: NodeId, port: PortIdx, src: &AudioFrame)
pub fn feed(&mut self, node: NodeId, port: PortIdx, src: &AudioFrame)
Seeds a node’s output port from an external frame, before a cycle.
Performs a bounded copy into the pre-sized scratch slot — no
reallocation. Used to inject audio into a source node’s output before
calling Graph::process_cycle. Out-of-range node/port is a silent
no-op (never panics).
Sourcepub fn read_output(&self, node: NodeId, port: PortIdx) -> Option<&AudioFrame>
pub fn read_output(&self, node: NodeId, port: PortIdx) -> Option<&AudioFrame>
Borrows a node’s output frame after a cycle (tapping a node’s output).
Returns None if the node or port is out of range — never panics.
Sourcepub fn read_input(&self, node: NodeId, port: PortIdx) -> Option<&AudioFrame>
pub fn read_input(&self, node: NodeId, port: PortIdx) -> Option<&AudioFrame>
Borrows the input frame that reached a node after a cycle.
Sinks have zero outputs, so callers read a sink’s consumed audio through
its input slot. Returns None if the node or port is out of range.
Sourcepub fn node_count(&self) -> usize
pub fn node_count(&self) -> usize
Returns the number of nodes in the graph.
Sourcepub fn link_count(&self) -> usize
pub fn link_count(&self) -> usize
Returns the number of links in the graph.
Sourcepub fn is_compiled(&self) -> bool
pub fn is_compiled(&self) -> bool
Returns true if the graph has been compiled.
Sourcepub fn config(&self) -> GraphConfig
pub fn config(&self) -> GraphConfig
Returns the compile-time GraphConfig.
Before Graph::compile this returns the default (zeroed) config.