rill_core_dsp/macros/simple.rs
1//! Macro for creating a simple algorithm without parameters
2//!
3//! # Example
4//! ```
5//! use rill_core_dsp::simple_algorithm;
6//! use rill_core::math::Transcendental;
7//!
8//! simple_algorithm! {
9//! /// Simple gain
10//! #[derive(Debug, Clone, Copy)]
11//! pub struct Gain<T: Transcendental> {
12//! params: {
13//! /// Gain coefficient
14//! gain: T = T::from_f32(1.0),
15//! },
16//! state: {
17//! /// Last output value (for statistics)
18//! last_output: T = T::ZERO,
19//! },
20//! process: |this, input| {
21//! let output = input * this.gain;
22//! this.last_output = output;
23//! output
24//! }
25//! }
26//! }
27//! ```
28
29/// Macro for creating a simple algorithm without parameters
30///
31/// # Example
32/// ```
33/// use rill_core_dsp::simple_algorithm;
34/// use rill_core::math::Transcendental;
35///
36/// simple_algorithm! {
37/// /// Simple gain
38/// #[derive(Debug, Clone, Copy)]
39/// pub struct Gain<T: Transcendental> {
40/// params: {
41/// /// Gain coefficient
42/// gain: T = T::from_f32(1.0),
43/// },
44/// state: {
45/// /// Last output value (for statistics)
46/// last_output: T = T::ZERO,
47/// },
48/// process: |this, input| {
49/// let output = input * this.gain;
50/// this.last_output = output;
51/// output
52/// }
53/// }
54/// }
55/// ```
56#[macro_export]
57macro_rules! simple_algorithm {
58 (
59 $(#[$struct_meta:meta])*
60 $vis:vis struct $name:ident<$($generic:ident: $bound:path),+> {
61 params: {
62 $(
63 $(#[$param_meta:meta])*
64 $param_name:ident : $param_type:ty = $param_default:expr
65 ),* $(,)?
66 },
67 state: {
68 $(
69 $(#[$state_meta:meta])*
70 $state_name:ident : $state_type:ty = $state_default:expr
71 ),* $(,)?
72 },
73 process: $process:expr
74 }
75 ) => {
76 $(#[$struct_meta])*
77 $vis struct $name<$($generic: $bound),+> {
78 $(
79 $(#[$param_meta])*
80 pub $param_name: $param_type,
81 )*
82
83 $(
84 $(#[$state_meta])*
85 pub $state_name: $state_type,
86 )*
87 }
88
89 impl<$($generic: $bound),+> $name<$($generic),+> {
90 /// Create a new algorithm instance
91 pub fn new($($param_name: $param_type),*) -> Self {
92 Self {
93 $($param_name),*,
94 $($state_name: $state_default),*,
95 }
96 }
97 }
98
99 impl<$($generic: $bound),+> rill_core::traits::algorithm::Algorithm<T> for $name<$($generic),+>
100 where
101 T: rill_core::math::Transcendental,
102 {
103 fn init(&mut self, _sample_rate: f32) {}
104
105 fn reset(&mut self) {
106 $(
107 self.$state_name = $state_default;
108 )*
109 }
110
111 fn process(
112 &mut self,
113 input: Option<&[T]>,
114 output: &mut [T],
115 ) -> rill_core::traits::ProcessResult<()> {
116 let input = input.unwrap_or(&[]);
117 let len = input.len().min(output.len());
118 let process_fn: fn(&mut Self, T) -> T = $process;
119 for i in 0..len {
120 output[i] = process_fn(self, input[i]);
121 }
122 Ok(())
123 }
124
125 fn metadata(&self) -> rill_core::traits::algorithm::AlgorithmMetadata {
126 rill_core::traits::algorithm::AlgorithmMetadata {
127 name: stringify!($name),
128 category: rill_core::traits::algorithm::AlgorithmCategory::Utility,
129 description: stringify!($name),
130 author: "Rill",
131 version: env!("CARGO_PKG_VERSION"),
132 }
133 }
134 }
135 };
136}