use crate::{block::BlockId, sample::Sample};
#[derive(Debug, Clone)]
pub enum Parameter<S: Sample> {
Constant(S),
Modulated(BlockId),
}
impl<S: Sample> Parameter<S> {
#[inline]
pub fn get_value(&self, modulation_values: &[S]) -> S {
match self {
Parameter::Constant(value) => *value,
Parameter::Modulated(block_id) => {
modulation_values.get(block_id.0).copied().unwrap_or(S::ZERO)
}
}
}
}
#[derive(Debug, Clone)]
pub struct ModulationOutput {
pub name: &'static str,
pub min_value: f64,
pub max_value: f64,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parameter_constant_f32() {
let param = Parameter::Constant(42.0_f32);
let modulation_values: Vec<f32> = vec![];
let value = param.get_value(&modulation_values);
assert!((value - 42.0).abs() < 1e-6);
}
#[test]
fn test_parameter_constant_f64() {
let param = Parameter::Constant(42.0_f64);
let modulation_values: Vec<f64> = vec![];
let value = param.get_value(&modulation_values);
assert!((value - 42.0).abs() < 1e-12);
}
#[test]
fn test_parameter_modulated_valid_index_f32() {
let param = Parameter::Modulated(BlockId(1));
let modulation_values: Vec<f32> = vec![10.0, 20.0, 30.0];
let value = param.get_value(&modulation_values);
assert!((value - 20.0).abs() < 1e-6);
}
#[test]
fn test_parameter_modulated_valid_index_f64() {
let param = Parameter::Modulated(BlockId(1));
let modulation_values: Vec<f64> = vec![10.0, 20.0, 30.0];
let value = param.get_value(&modulation_values);
assert!((value - 20.0).abs() < 1e-12);
}
#[test]
fn test_parameter_modulated_out_of_bounds_returns_zero_f32() {
let param = Parameter::Modulated(BlockId(10));
let modulation_values: Vec<f32> = vec![10.0, 20.0, 30.0];
let value = param.get_value(&modulation_values);
assert!(value.abs() < 1e-10, "Out of bounds should return zero");
}
#[test]
fn test_parameter_modulated_out_of_bounds_returns_zero_f64() {
let param = Parameter::Modulated(BlockId(10));
let modulation_values: Vec<f64> = vec![10.0, 20.0, 30.0];
let value = param.get_value(&modulation_values);
assert!(value.abs() < 1e-15, "Out of bounds should return zero");
}
#[test]
fn test_parameter_modulated_empty_array_returns_zero_f32() {
let param = Parameter::Modulated(BlockId(0));
let modulation_values: Vec<f32> = vec![];
let value = param.get_value(&modulation_values);
assert!(value.abs() < 1e-10, "Empty array should return zero");
}
#[test]
fn test_parameter_modulated_empty_array_returns_zero_f64() {
let param = Parameter::Modulated(BlockId(0));
let modulation_values: Vec<f64> = vec![];
let value = param.get_value(&modulation_values);
assert!(value.abs() < 1e-15, "Empty array should return zero");
}
#[test]
fn test_parameter_modulated_index_zero_f32() {
let param = Parameter::Modulated(BlockId(0));
let modulation_values: Vec<f32> = vec![99.0, 20.0, 30.0];
let value = param.get_value(&modulation_values);
assert!((value - 99.0).abs() < 1e-6);
}
#[test]
fn test_parameter_modulated_index_zero_f64() {
let param = Parameter::Modulated(BlockId(0));
let modulation_values: Vec<f64> = vec![99.0, 20.0, 30.0];
let value = param.get_value(&modulation_values);
assert!((value - 99.0).abs() < 1e-12);
}
#[test]
fn test_parameter_constant_negative_value_f32() {
let param = Parameter::Constant(-42.0_f32);
let modulation_values: Vec<f32> = vec![];
let value = param.get_value(&modulation_values);
assert!((value - (-42.0)).abs() < 1e-6);
}
#[test]
fn test_parameter_constant_zero_f32() {
let param = Parameter::Constant(0.0_f32);
let modulation_values: Vec<f32> = vec![];
let value = param.get_value(&modulation_values);
assert!(value.abs() < 1e-10);
}
#[test]
fn test_parameter_modulated_negative_value_f32() {
let param = Parameter::Modulated(BlockId(0));
let modulation_values: Vec<f32> = vec![-50.0];
let value = param.get_value(&modulation_values);
assert!((value - (-50.0)).abs() < 1e-6);
}
#[test]
fn test_modulation_output_creation() {
let output = ModulationOutput {
name: "test",
min_value: -1.0,
max_value: 1.0,
};
assert_eq!(output.name, "test");
assert!((output.min_value - (-1.0)).abs() < 1e-10);
assert!((output.max_value - 1.0).abs() < 1e-10);
}
#[test]
fn test_parameter_clone_f32() {
let param1 = Parameter::Constant(42.0_f32);
let param2 = param1.clone();
let modulation_values: Vec<f32> = vec![];
let value1 = param1.get_value(&modulation_values);
let value2 = param2.get_value(&modulation_values);
assert!((value1 - value2).abs() < 1e-10);
}
#[test]
fn test_parameter_modulated_clone_f32() {
let param1 = Parameter::Modulated::<f32>(BlockId(1));
let param2 = param1.clone();
let modulation_values: Vec<f32> = vec![10.0, 20.0];
let value1 = param1.get_value(&modulation_values);
let value2 = param2.get_value(&modulation_values);
assert!((value1 - value2).abs() < 1e-10);
}
}