rawdio/effects/waveshaper/
waveshaper_node.rs1use super::{parameters::*, waveshaper_processor::WaveshaperProcessor};
2use crate::{commands::Id, graph::DspNode, parameter::*, prelude::*, utility::create_parameters};
3
4pub struct Waveshaper {
10 pub node: GraphNode,
12
13 params: Parameters,
14}
15
16impl DspNode for Waveshaper {
17 fn get_parameters_mut(&mut self) -> &mut Parameters {
18 &mut self.params
19 }
20}
21
22impl Waveshaper {
23 pub fn tanh(context: &dyn Context, channel_count: usize) -> Self {
26 let shaper = |input: f32| {
27 const CONSTANT: f32 = 2.0;
28 CONSTANT * (input / CONSTANT).tanh()
29 };
30
31 Self::new(context, channel_count, &shaper)
32 }
33
34 pub fn soft_saturator(context: &dyn Context, channel_count: usize, threshold: Level) -> Self {
37 let threshold = threshold.as_linear() as f32;
38 assert!(0.0 <= threshold);
39 assert!(threshold <= 1.0);
40
41 let shaper = move |input: f32| {
42 if input < threshold {
43 input
44 } else {
45 threshold
46 + (input - threshold)
47 / (1.0 + ((input - threshold) / (1.0 - threshold)).powf(2.0))
48 }
49 };
50
51 Self::new(context, channel_count, &shaper)
52 }
53
54 pub fn hard_clip(context: &dyn Context, channel_count: usize, threshold: Level) -> Self {
57 let threshold = threshold.as_linear() as f32;
58
59 let shaper = Box::new(move |input: f32| {
60 if input < -threshold {
61 return -threshold;
62 }
63
64 if input > threshold {
65 return threshold;
66 }
67
68 input
69 });
70
71 Self::new(context, channel_count, &shaper)
72 }
73
74 pub fn new(context: &dyn Context, channel_count: usize, shaper: &dyn Fn(f32) -> f32) -> Self {
76 let id = Id::generate();
77
78 let (params, realtime_params) = create_parameters(
79 id,
80 context,
81 [
82 (
83 "overdrive",
84 ParameterRange::new(
85 OVERDRIVE_PARAMETER_DEFAULT,
86 OVERDRIVE_PARAMETER_MIN,
87 OVERDRIVE_PARAMETER_MAX,
88 ),
89 ),
90 (
91 "mix",
92 ParameterRange::new(
93 MIX_PARAMETER_DEFAULT,
94 MIX_PARAMETER_MIN,
95 MIX_PARAMETER_MAX,
96 ),
97 ),
98 ],
99 );
100
101 let processor = Box::new(WaveshaperProcessor::new(
102 shaper,
103 context.get_sample_rate(),
104 context.maximum_frame_count(),
105 ));
106
107 Self {
108 node: GraphNode::new(
109 id,
110 context,
111 channel_count,
112 channel_count,
113 processor,
114 realtime_params,
115 ),
116 params,
117 }
118 }
119
120 pub fn overdrive(&mut self) -> &mut AudioParameter {
122 self.get_parameter_mut("overdrive")
123 }
124
125 pub fn mix(&mut self) -> &mut AudioParameter {
127 self.get_parameter_mut("mix")
128 }
129}