1pub mod action;
7pub mod algorithm;
8mod error;
9pub mod node;
10pub mod param;
11pub mod port;
12pub mod processable;
13
14pub use action::*;
16pub use algorithm::*;
17pub use error::*;
18pub use node::*;
19pub use param::*;
20pub use port::*;
21pub use processable::*;
22
23pub const DEFAULT_BLOCK_SIZE: usize = 64;
29
30pub type MonoBlock<T, const BUF_SIZE: usize> = [T; BUF_SIZE];
32
33pub type StereoBlock<T, const BUF_SIZE: usize> = [MonoBlock<T, BUF_SIZE>; 2];
35
36pub type ControlValue<T> = T;
38
39pub mod prelude {
45 pub use super::{
47 SignalNode,
49 NodeCategory,
50 NodeId,
52 NodeMetadata,
53 NodeState,
54
55 NodeTypeId,
56 ParamMetadata,
57
58 ParamRange,
59 ParamType,
60 ParamValue,
61 ParameterError,
62
63 ParameterId,
65 ParameterResult,
66 Port,
67
68 PortDirection,
69 PortId,
71 PortType,
72 ProcessError,
73 ProcessResult,
75 Processor,
76 Sink,
77
78 Source,
79 DEFAULT_BLOCK_SIZE,
81 };
82
83 pub use crate::math::Transcendental;
85}
86
87pub trait IntoParamValue: Sized {
93 fn into_param_value(self) -> ParamValue;
95
96 fn from_param_value(value: ParamValue) -> Option<Self>;
98}
99
100impl IntoParamValue for f32 {
101 fn into_param_value(self) -> ParamValue {
102 ParamValue::Float(self)
103 }
104
105 fn from_param_value(value: ParamValue) -> Option<Self> {
106 value.as_f32()
107 }
108}
109
110impl IntoParamValue for i32 {
111 fn into_param_value(self) -> ParamValue {
112 ParamValue::Int(self)
113 }
114
115 fn from_param_value(value: ParamValue) -> Option<Self> {
116 value.as_i32()
117 }
118}
119
120impl IntoParamValue for bool {
121 fn into_param_value(self) -> ParamValue {
122 ParamValue::Bool(self)
123 }
124
125 fn from_param_value(value: ParamValue) -> Option<Self> {
126 value.as_bool()
127 }
128}
129
130impl IntoParamValue for String {
131 fn into_param_value(self) -> ParamValue {
132 ParamValue::String(self)
133 }
134
135 fn from_param_value(value: ParamValue) -> Option<Self> {
136 match value {
137 ParamValue::String(s) => Some(s),
138 ParamValue::Choice(s) => Some(s),
139 _ => None,
140 }
141 }
142}
143
144pub trait AsAny: 'static {
150 fn as_any(&self) -> &dyn std::any::Any;
152
153 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
155}
156
157impl<T: 'static> AsAny for T {
158 fn as_any(&self) -> &dyn std::any::Any {
159 self
160 }
161
162 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
163 self
164 }
165}
166
167#[cfg(test)]
172mod tests {
173 use super::prelude::*;
174 use crate::traits::IntoParamValue;
175
176 #[test]
177 fn test_prelude_imports() {
178 let _node_id = NodeId(0);
180 let _port_id = PortId::audio_in(_node_id, 0);
181 let _param_id = ParameterId::new("test").unwrap();
182
183 let f: f32 = 42.0;
185 let pv = f.into_param_value();
186 assert_eq!(pv.as_f32(), Some(42.0));
187
188 let back = f32::from_param_value(pv);
189 assert_eq!(back, Some(42.0));
190 }
191
192 #[test]
193 fn test_param_value_conversions() {
194 let f = ParamValue::Float(42.0);
195 assert_eq!(f.as_f32(), Some(42.0));
196 assert_eq!(f.as_i32(), Some(42));
197 assert_eq!(f.as_bool(), Some(true));
198
199 let i = ParamValue::Int(0);
200 assert_eq!(i.as_f32(), Some(0.0));
201 assert_eq!(i.as_i32(), Some(0));
202 assert_eq!(i.as_bool(), Some(false));
203
204 let b = ParamValue::Bool(true);
205 assert_eq!(b.as_f32(), Some(1.0));
206 assert_eq!(b.as_i32(), Some(1));
207 assert_eq!(b.as_bool(), Some(true));
208 }
209
210 #[test]
211 fn test_parameter_id_validation() {
212 assert!(ParameterId::new("gain").is_ok());
213 assert!(ParameterId::new("cutoff_freq").is_ok());
214 assert!(ParameterId::new("delay_time_2").is_ok());
215
216 assert!(ParameterId::new("").is_err());
217 assert!(ParameterId::new("1gain").is_err());
218 assert!(ParameterId::new("_gain").is_err());
219 assert!(ParameterId::new("gain.value").is_err());
220 }
221
222 #[test]
223 fn test_port_id_creation() {
224 let node = NodeId(42);
225
226 let audio_in = PortId::audio_in(node, 0);
227 assert_eq!(audio_in.node_id(), node);
228 assert_eq!(audio_in.port_type(), PortType::Signal);
229 assert_eq!(audio_in.direction(), PortDirection::Input);
230 assert_eq!(audio_in.index(), 0);
231 assert!(audio_in.is_input());
232 assert!(audio_in.is_audio());
233
234 let clock_out = PortId::clock_out(node, 0);
235 assert_eq!(clock_out.port_type(), PortType::Clock);
236 assert!(clock_out.is_output());
237 assert!(clock_out.is_clock());
238
239 let feedback_in = PortId::feedback_in(node, 0);
240 assert_eq!(feedback_in.port_type(), PortType::Feedback);
241 assert!(feedback_in.is_input());
242 assert!(feedback_in.is_feedback());
243 }
244
245 #[test]
246 fn test_node_metadata() {
247 let metadata = NodeMetadata {
248 name: "TestNode".to_string(),
249 type_name: None,
250 category: NodeCategory::Processor,
251 description: "A test node".to_string(),
252 author: "Rill".to_string(),
253 version: "1.0".to_string(),
254 signal_inputs: 2,
255 signal_outputs: 2,
256 control_inputs: 1,
257 control_outputs: 0,
258 clock_inputs: 1,
259 clock_outputs: 0,
260 feedback_ports: 0,
261 parameters: vec![],
262 };
263
264 assert_eq!(metadata.name, "TestNode");
265 assert_eq!(metadata.category, NodeCategory::Processor);
266 assert_eq!(metadata.signal_inputs, 2);
267 }
268
269 #[test]
270 fn test_param_range() {
271 let range = ParamRange::new().with_min(0.0).with_max(1.0).with_step(0.1);
272
273 assert!(range.contains(0.5));
274 assert!(!range.contains(1.5));
275 assert_eq!(range.clamp(1.5), 1.0);
276 assert_eq!(range.clamp(-0.5), 0.0);
277 }
278
279 #[test]
280 fn test_default_block_size() {
281 assert_eq!(DEFAULT_BLOCK_SIZE, 64);
282 }
283}