macro_rules! stateful_dsp_node_type { ($node_type: ident, $struct_type: ident => $func_name: ident $jit_name: literal $signature: literal doc $doc: literal inputs $($idx: literal $inp: literal)* outputs $($idxo: literal $out: literal)*) => { ... }; }
Expand description
This macro can help you defining new stateful DSP nodes.
use synfx_dsp_jit::*;
struct MyDSPNode {
value: f64,
}
impl MyDSPNode {
fn reset(&mut self, _state: &mut DSPState) {
*self = Self::default();
}
}
impl Default for MyDSPNode {
fn default() -> Self {
Self { value: 0.0 }
}
}
extern "C" fn process_my_dsp_node(my_state: *mut MyDSPNode) -> f64 {
let mut my_state = unsafe { &mut *my_state };
my_state.value += 1.0;
my_state.value
}
// DIYNodeType is the type that is newly defined here, that one you
// pass to DSPNodeTypeLibrary::add
synfx_dsp_jit::stateful_dsp_node_type! {
DIYNodeType, MyDSPNode => process_my_dsp_node "my_dsp" "Sr"
doc
"This is a simple counter. It counts by increments of 1.0 everytime it's called."
inputs
outputs
0 "sum"
}
// Then use the type by adding it:
fn make_library() -> DSPNodeTypeLibrary {
let mut lib = DSPNodeTypeLibrary::new();
lib.add(DIYNodeType::new_ref());
lib
}
You might’ve guessed, process_my_dsp_node
is the function identifier in the Rust
code. The "my_dsp"
is the name you can use to refer to this in crate::ASTNode::Call:
ASTNode::Call("my_dsp".to_string(), 1, ...)
.
Attention: Make sure to provide unique state IDs here!
The "Sr"
is a string that specifies the signature of the function. Following characters
are available:
- “v” - A floating point value
- “D” - The global crate::DSPState pointer
- “S” - The node specific state pointer (
MyDSPNode
) - “M” - A pointer to the multi return value array, of type
*mut [f64; 5]
. These can be accessed by the variables “%1” to “%5” after the call. - “r” - Must be specified as last one, defines that this function returns something.