pub struct ProcessorChain { /* private fields */ }Expand description
Ordered processor chain with all realtime scratch allocated by prepare.
A chain runs its nodes only once prepared: before its first prepare,
and after a push until the next one, it passes its input through.
Each node gets the context of the audio it receives: the chain input’s, moved back by the latency of the nodes before it, so a sample-addressed node (a fade, automation) after a lookahead acts on the audio it scales.
Implementations§
Source§impl ProcessorChain
impl ProcessorChain
Sourcepub fn new(layout: ChannelLayout) -> Self
pub fn new(layout: ChannelLayout) -> Self
Creates an empty chain for a validated layout.
Sourcepub fn push(
&mut self,
processor: impl Processor + 'static,
) -> Result<(), ChainError>
pub fn push( &mut self, processor: impl Processor + 'static, ) -> Result<(), ChainError>
Adds a processor outside the realtime path. The chain passes its input through until it is prepared again.
§Errors
Returns ChainError::MultipleInputs, and leaves the chain as it
was, for a processor that reads more than one input per output.
Sourcepub fn set_bypass(&mut self, bypass: bool)
pub fn set_bypass(&mut self, bypass: bool)
Bypasses the whole chain, or ends the bypass, outside the realtime path.
A bypassed chain plays its input delayed by its
Self::latency_samples, which it keeps reporting, so a host that
compensates the latency stays aligned; and its nodes keep running on
the input, so ending the bypass plays what they make of the current
audio, never audio from before the bypass. The delayed input comes
from a record the chain keeps from its first call here on (either
way; it allocates it then, or at the next prepare): bypassed sooner
after that than its latency, it plays silence for the part it has no
record of. A chain never bypassed keeps no record and costs nothing.
Sourcepub fn passes_through(&self) -> bool
pub fn passes_through(&self) -> bool
Whether Self::process copies its input to its output unchanged
and touches nothing else, so a host may skip it: the chain is empty,
or not prepared since its last push. (A bypassed chain still runs its
nodes.)
Sourcepub fn is_prepared(&self) -> bool
pub fn is_prepared(&self) -> bool
Whether the chain has been prepared since its processors last changed, so it runs them.
Sourcepub fn prepare(&mut self, sample_rate: u32, max_block: usize)
pub fn prepare(&mut self, sample_rate: u32, max_block: usize)
Allocates scratch and prepares every node.
Sourcepub fn prepare_nodes(&mut self, sample_rate: u32, max_block: usize)
pub fn prepare_nodes(&mut self, sample_rate: u32, max_block: usize)
Prepares every node but leaves the chain without scratch of its own:
a chain run only through Self::process_in_place works in its
caller’s buffers, so many such chains cost only their nodes’ state
(a bypassed one also a block of scratch). Self::process passes
its input through until Self::prepare.
Sourcepub fn process_in_place(
&mut self,
ctx: &ProcessCtx,
buffer: &mut [Vec<f32>; 2],
spare: &mut [Vec<f32>; 2],
frames: usize,
)
pub fn process_in_place( &mut self, ctx: &ProcessCtx, buffer: &mut [Vec<f32>; 2], spare: &mut [Vec<f32>; 2], frames: usize, )
Processes the first frames samples of each buffer channel in
place without allocating, the way Self::process would: spare
holds each node’s output before it becomes the next node’s input, so
the two may trade allocations. Both need frames samples per channel
of the layout.
Sourcepub fn latency_samples(&self) -> u32
pub fn latency_samples(&self) -> u32
Sum of serial node latencies; none while the chain is not prepared and so passes its input through.
Sourcepub fn history_samples(&self) -> u32
pub fn history_samples(&self) -> u32
Sum of serial processor settling horizons, excluding their delays.
Sourcepub fn process(
&mut self,
ctx: &ProcessCtx,
inputs: &[&[f32]],
outputs: &mut [&mut [f32]],
)
pub fn process( &mut self, ctx: &ProcessCtx, inputs: &[&[f32]], outputs: &mut [&mut [f32]], )
Processes one block without allocating: the first n samples of each
output channel of the layout, for n the shortest input or output
channel. A block longer than the prepared max_block runs in pieces,
as consecutive blocks would. Without an input or output channel for
every channel of the layout there is nothing to process, and the
outputs given are silenced.
Sourcepub fn save_state(&self) -> StateBlob
pub fn save_state(&self) -> StateBlob
Serializes each processor state with length framing, then the record of the input a bypass plays.
Sourcepub fn load_state(&mut self, state: &StateBlob) -> Result<(), ChainStateError>
pub fn load_state(&mut self, state: &StateBlob) -> Result<(), ChainStateError>
Restores a state saved by a chain of the same nodes, prepared alike, whole or not at all: when a node refuses its part, the nodes before it get their own state back.
A bypass record the saving chain did not keep (never bypassed) leaves this one’s empty, as a first bypass finds it; one this chain does not keep is dropped.
§Errors
Returns where and why the state was refused: the node count or
framing differ, or the record has another length
(ChainStateError::node None), or a node refused its part.
Sourcepub fn node_state(&self, index: usize) -> Option<StateBlob>
pub fn node_state(&self, index: usize) -> Option<StateBlob>
The history of the node at index alone, as its
Processor::save_state makes it; None past the last node.
With Self::load_node_state a host that rebuilds a chain with an
edited node hands each node it kept, or replaced with one of the same
kind, the history of the one before it.
Sourcepub fn load_node_state(
&mut self,
index: usize,
state: &StateBlob,
) -> Result<(), StateError>
pub fn load_node_state( &mut self, index: usize, state: &StateBlob, ) -> Result<(), StateError>
Restores the node at index from a state Self::node_state took,
whole or not at all.
§Errors
Returns StateError::Mismatch past the last node, and otherwise
what the node’s Processor::load_state refuses, leaving it as it
was.