Skip to main content

rill_core_dsp/macros/
generator.rs

1//! Macro for creating a generator
2//!
3//! # Example
4//! use rill_core_dsp::generator_algorithm;
5//! use rill_core::math::Transcendental;
6//!
7//! generator_algorithm! {
8//!     /// Sine generator
9//!     #[derive(Debug, Clone, Copy)]
10//!     pub struct SineGen<T: Transcendental> {
11//!         params: {
12//!             freq: T = T::from_f32(440.0),
13//!             amp: T = T::from_f32(0.5),
14//!         },
15//!         state: {
16//!             phase: T = T::ZERO,
17//!         },
18//!         generate: |this| {
19//!             let output = (this.phase * T::from_f32(2.0 * std::f32::consts::PI)).sin() * this.amp;
20//!             let phase_inc = this.freq / T::from_f32(this.sample_rate);
21//!             this.phase = (this.phase + phase_inc) % T::from_f32(1.0);
22//!             output
23//!         }
24//!     }
25//! }
26
27/// Macro for creating a generator
28///
29/// # Example
30/// use rill_core_dsp::generator_algorithm;
31/// use rill_core::math::Transcendental;
32///
33/// generator_algorithm! {
34///     /// Sine generator
35///     #[derive(Debug, Clone, Copy)]
36///     pub struct SineGen<T: Transcendental> {
37///         params: {
38///             freq: T = T::from_f32(440.0),
39///             amp: T = T::from_f32(0.5),
40///         },
41///         state: {
42///             phase: T = T::ZERO,
43///         },
44///         generate: |this| {
45///             let output = (this.phase * T::from_f32(2.0 * std::f32::consts::PI)).sin() * this.amp;
46///             let phase_inc = this.freq / T::from_f32(this.sample_rate);
47///             this.phase = (this.phase + phase_inc) % T::from_f32(1.0);
48///             output
49///         }
50///     }
51/// }
52#[macro_export]
53macro_rules! generator_algorithm {
54    (
55        $(#[$struct_meta:meta])*
56        $vis:vis struct $name:ident<$($generic:ident: $bound:path),+> {
57            params: {
58                $(
59                    $(#[$param_meta:meta])*
60                    $param_name:ident : $param_type:ty = $param_default:expr
61                ),* $(,)?
62            },
63            state: {
64                $(
65                    $(#[$state_meta:meta])*
66                    $state_name:ident : $state_type:ty = $state_default:expr
67                ),* $(,)?
68            },
69            generate: $generate:expr
70        }
71    ) => {
72        $(#[$struct_meta])*
73        $vis struct $name<$($generic: $bound),+> {
74            $(
75                $(#[$param_meta])*
76                pub $param_name: $param_type,
77            )*
78
79            $(
80                $(#[$state_meta])*
81                pub $state_name: $state_type,
82            )*
83
84            /// Sample rate
85            pub sample_rate: f32,
86        }
87
88        impl<$($generic: $bound),+> $name<$($generic),+> {
89            /// Create a new generator instance
90            pub fn new($($param_name: $param_type),*) -> Self {
91                Self {
92                    $($param_name),*,
93                    $($state_name: $state_default),*,
94                    sample_rate: 44100.0,
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                self.sample_rate = sample_rate;
105            }
106
107            fn reset(&mut self) {
108                $(
109                    self.$state_name = $state_default;
110                )*
111            }
112
113            fn process(
114                &mut self,
115                _input: Option<&[T]>,
116                output: &mut [T],
117            ) -> rill_core::traits::ProcessResult<()> {
118                let generate_fn: fn(&mut Self) -> T = $generate;
119                for out in output.iter_mut() {
120                    *out = generate_fn(self);
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::Generator,
129                    description: stringify!($name),
130                    author: "Rill",
131                    version: env!("CARGO_PKG_VERSION"),
132                }
133            }
134        }
135    };
136}