pub mod algorithm;
pub mod bridge;
pub mod buffer_view;
mod error;
pub mod multichannel_algorithm;
pub mod param;
pub mod parameter_write;
pub mod rack;
pub use algorithm::*;
pub use buffer_view::*;
pub use error::*;
pub use multichannel_algorithm::*;
pub use param::*;
pub use parameter_write::*;
pub use rack::*;
pub const DEFAULT_BLOCK_SIZE: usize = 64;
pub type MonoBlock<T, const BUF_SIZE: usize> = [T; BUF_SIZE];
pub type StereoBlock<T, const BUF_SIZE: usize> = [MonoBlock<T, BUF_SIZE>; 2];
pub type ControlValue<T> = T;
pub mod prelude {
pub use super::{
BufferView,
Eurorack,
ParamMetadata,
ParamRange,
ParamType,
ParamValue,
ParameterError,
ParameterId,
ParameterResult,
ParameterWrite,
ProcessError,
ProcessResult, DEFAULT_BLOCK_SIZE,
};
pub use crate::math::Transcendental;
}
pub trait IntoParamValue: Sized {
fn into_param_value(self) -> ParamValue;
fn from_param_value(value: ParamValue) -> Option<Self>;
}
impl IntoParamValue for f32 {
fn into_param_value(self) -> ParamValue {
ParamValue::Float(self)
}
fn from_param_value(value: ParamValue) -> Option<Self> {
value.as_f32()
}
}
impl IntoParamValue for i32 {
fn into_param_value(self) -> ParamValue {
ParamValue::Int(self)
}
fn from_param_value(value: ParamValue) -> Option<Self> {
value.as_i32()
}
}
impl IntoParamValue for bool {
fn into_param_value(self) -> ParamValue {
ParamValue::Bool(self)
}
fn from_param_value(value: ParamValue) -> Option<Self> {
value.as_bool()
}
}
impl IntoParamValue for String {
fn into_param_value(self) -> ParamValue {
ParamValue::String(self)
}
fn from_param_value(value: ParamValue) -> Option<Self> {
match value {
ParamValue::String(s) => Some(s),
ParamValue::Choice(s) => Some(s),
_ => None,
}
}
}
pub trait AsAny: 'static {
fn as_any(&self) -> &dyn std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
}
impl<T: 'static> AsAny for T {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
#[cfg(test)]
mod tests {
use super::prelude::*;
#[test]
fn test_param_value_conversions() {
let f = ParamValue::Float(42.0);
assert_eq!(f.as_f32(), Some(42.0));
assert_eq!(f.as_i32(), Some(42));
assert_eq!(f.as_bool(), Some(true));
let i = ParamValue::Int(0);
assert_eq!(i.as_f32(), Some(0.0));
assert_eq!(i.as_i32(), Some(0));
assert_eq!(i.as_bool(), Some(false));
let b = ParamValue::Bool(true);
assert_eq!(b.as_f32(), Some(1.0));
assert_eq!(b.as_i32(), Some(1));
assert_eq!(b.as_bool(), Some(true));
}
#[test]
fn test_parameter_id_validation() {
assert!(ParameterId::new("gain").is_ok());
assert!(ParameterId::new("cutoff_freq").is_ok());
assert!(ParameterId::new("delay_time_2").is_ok());
assert!(ParameterId::new("").is_err());
assert!(ParameterId::new("1gain").is_err());
assert!(ParameterId::new("_gain").is_err());
assert!(ParameterId::new("gain.value").is_ok());
}
#[test]
fn test_param_range() {
let range = ParamRange::new().with_min(0.0).with_max(1.0).with_step(0.1);
assert!(range.contains(0.5));
assert!(!range.contains(1.5));
assert_eq!(range.clamp(1.5), 1.0);
assert_eq!(range.clamp(-0.5), 0.0);
}
#[test]
fn test_default_block_size() {
assert_eq!(DEFAULT_BLOCK_SIZE, 64);
}
}