pub trait Patch {
// Required method
fn patch(
&mut self,
data: &ParamData,
path: &[u32],
) -> Result<(), PatchError>;
// Provided methods
fn patch_event(&mut self, event: &NodeEventType) -> bool { ... }
fn patch_list(&mut self, event_list: NodeEventList<'_>) -> bool { ... }
}Expand description
Fine-grained parameter patching.
This trait allows a type to perform patching on itself, applying patches generated from another instance.
For more information, see the module docs.
§Examples
Like with Diff, the typical Patch usage is simple.
use firewheel_core::{diff::Patch, event::*, node::*};
#[derive(Patch)]
struct MyParams {
a: f32,
b: f32,
}
struct MyProcessor {
params: MyParams,
}
impl AudioNodeProcessor for MyProcessor {
fn process(
&mut self,
inputs: &[&[f32]],
outputs: &mut [&mut [f32]],
events: NodeEventList,
proc_info: &ProcInfo,
scratch_buffers: ScratchBuffers,
) -> ProcessStatus {
// Synchronize `params` from the event list.
self.params.patch_list(events);
// ...
ProcessStatus::outputs_not_silent()
}
}Patch::patch_list is a convenience trait method
that takes a NodeEventList by value, applies any
parameter patches that may be present, and returns
a boolean indicating whether any parameters have changed.
If you need finer access to the event list, you can apply patches more directly.
impl AudioNodeProcessor for MyProcessor {
fn process(
&mut self,
inputs: &[&[f32]],
outputs: &mut [&mut [f32]],
mut events: NodeEventList,
proc_info: &ProcInfo,
scratch_buffers: ScratchBuffers,
) -> ProcessStatus {
events.for_each(|e| {
// You can take the whole event, which may
// or may not actually contain a parameter:
self.params.patch_event(e);
// Or match on the event and provide
// each element directly:
match e {
NodeEventType::Param { data, path } => {
// This allows you to handle errors as well.
let _ = self.params.patch(data, &path);
}
_ => {}
}
});
// ...
ProcessStatus::outputs_not_silent()
}
}§Manual implementation
Like with Diff, types like parameters should prefer the Patch derive macro.
Nonetheless, Firewheel provides a few tools to make manual implementations easy.
use firewheel_core::{diff::{Patch, PatchError}, event::ParamData};
struct MyParams {
a: f32,
b: (bool, bool)
}
impl Patch for MyParams {
fn patch(&mut self, data: &ParamData, path: &[u32]) -> Result<(), PatchError> {
match path {
[0] => {
// You can defer to `f32`'s `Patch` implementation, or simply
// apply the data directly like we do here.
self.a = data.try_into()?;
Ok(())
}
// Shortening the path slice one element at a time as we descend the tree
// allows nested types to see the path as they expect it.
[1, tail @ ..] => {
self.b.patch(data, tail)
}
_ => Err(PatchError::InvalidPath)
}
}
}Required Methods§
Sourcefn patch(&mut self, data: &ParamData, path: &[u32]) -> Result<(), PatchError>
fn patch(&mut self, data: &ParamData, path: &[u32]) -> Result<(), PatchError>
Patch self according to the incoming data.
This will generally be called from within
the audio thread.
data is intentionally made a shared reference.
This should make accidental syscalls due to
additional allocations or drops more difficult.
If you find yourself reaching for interior
mutability, consider whether you’re building
realtime-appropriate behavior.
Provided Methods§
Sourcefn patch_event(&mut self, event: &NodeEventType) -> bool
fn patch_event(&mut self, event: &NodeEventType) -> bool
Patch a set of parameters with incoming events.
Returns true if any parameters have changed.
This is useful as a convenience method for extracting the path
and data components from a NodeEventType. Errors produced
here are ignored.
Sourcefn patch_list(&mut self, event_list: NodeEventList<'_>) -> bool
fn patch_list(&mut self, event_list: NodeEventList<'_>) -> bool
Patch a set of parameters with a list of incoming events.
Returns true if any parameters have changed.
This is useful as a convenience method for patching parameters
directly from a NodeEventList. Errors produced here are ignored.