use super::{parameters::*, waveshaper_processor::WaveshaperProcessor};
use crate::{commands::Id, graph::DspNode, parameter::*, prelude::*, utility::create_parameters};
pub struct Waveshaper {
pub node: GraphNode,
params: Parameters,
}
impl DspNode for Waveshaper {
fn get_parameters_mut(&mut self) -> &mut Parameters {
&mut self.params
}
}
impl Waveshaper {
pub fn tanh(context: &dyn Context, channel_count: usize) -> Self {
let shaper = |input: f32| {
const CONSTANT: f32 = 2.0;
CONSTANT * (input / CONSTANT).tanh()
};
Self::new(context, channel_count, &shaper)
}
pub fn soft_saturator(context: &dyn Context, channel_count: usize, threshold: Level) -> Self {
let threshold = threshold.as_linear() as f32;
assert!(0.0 <= threshold);
assert!(threshold <= 1.0);
let shaper = move |input: f32| {
if input < threshold {
input
} else {
threshold
+ (input - threshold)
/ (1.0 + ((input - threshold) / (1.0 - threshold)).powf(2.0))
}
};
Self::new(context, channel_count, &shaper)
}
pub fn hard_clip(context: &dyn Context, channel_count: usize, threshold: Level) -> Self {
let threshold = threshold.as_linear() as f32;
let shaper = Box::new(move |input: f32| {
if input < -threshold {
return -threshold;
}
if input > threshold {
return threshold;
}
input
});
Self::new(context, channel_count, &shaper)
}
pub fn new(context: &dyn Context, channel_count: usize, shaper: &dyn Fn(f32) -> f32) -> Self {
let id = Id::generate();
let (params, realtime_params) = create_parameters(
id,
context,
[
(
"overdrive",
ParameterRange::new(
OVERDRIVE_PARAMETER_DEFAULT,
OVERDRIVE_PARAMETER_MIN,
OVERDRIVE_PARAMETER_MAX,
),
),
(
"mix",
ParameterRange::new(
MIX_PARAMETER_DEFAULT,
MIX_PARAMETER_MIN,
MIX_PARAMETER_MAX,
),
),
],
);
let processor = Box::new(WaveshaperProcessor::new(
shaper,
context.get_sample_rate(),
context.maximum_frame_count(),
));
Self {
node: GraphNode::new(
id,
context,
channel_count,
channel_count,
processor,
realtime_params,
),
params,
}
}
pub fn overdrive(&mut self) -> &mut AudioParameter {
self.get_parameter_mut("overdrive")
}
pub fn mix(&mut self) -> &mut AudioParameter {
self.get_parameter_mut("mix")
}
}