1use aether_ndk::prelude::*;
6
7#[aether_node]
9pub struct Tremolo {
10 #[param(name = "Rate", min = 0.1, max = 20.0, default = 4.0)]
11 rate: f32,
12 #[param(name = "Depth", min = 0.0, max = 1.0, default = 0.5)]
13 depth: f32,
14 phase: f32,
16}
17
18impl DspProcess for Tremolo {
19 fn process(
20 &mut self,
21 inputs: &NodeInputs,
22 output: &mut NodeOutput,
23 params: &mut ParamBlock,
24 sample_rate: f32,
25 ) {
26 let input = inputs.get(0);
27 for (i, out) in output.iter_mut().enumerate() {
28 let rate = params.get(0).current;
29 let depth = params.get(1).current;
30 let lfo = 1.0 - depth * 0.5 * (1.0 - (self.phase * std::f32::consts::TAU).cos());
32 *out = input[i] * lfo;
33 self.phase = (self.phase + rate / sample_rate).fract();
34 params.tick_all();
35 }
36 }
37}
38
39fn main() {
40 let t = Tremolo::default();
42 println!("Node type: {}", Tremolo::type_name());
43 println!("Param count: {}", Tremolo::PARAM_COUNT);
44 for def in Tremolo::param_defs() {
45 println!(" {} [{:.1}–{:.1}] default={:.2}", def.name, def.min, def.max, def.default);
46 }
47
48 let _boxed: Box<dyn aether_ndk::DspNode> = into_node(t);
50 println!("\nNode wrapped and ready for the graph ✓");
51}