wavecraft_processors/
gain.rs1use wavecraft_dsp::{ParamRange, ParamSpec, Processor, ProcessorParams, Transport};
4
5#[derive(Debug, Default, Clone)]
7pub struct GainParams {
8 pub level: f32,
10}
11
12impl ProcessorParams for GainParams {
13 fn param_specs() -> &'static [ParamSpec] {
14 static SPECS: [ParamSpec; 1] = [ParamSpec {
15 name: "Level",
16 id_suffix: "level",
17 range: ParamRange::Skewed {
18 min: 0.0,
19 max: 2.0,
20 factor: 2.5, },
22 default: 1.0,
23 unit: "x",
24 group: None,
25 }];
26 &SPECS
27 }
28
29 fn from_param_defaults() -> Self {
30 Self { level: 1.0 }
31 }
32
33 fn apply_plain_values(&mut self, values: &[f32]) {
34 if let Some(level) = values.first() {
35 self.level = *level;
36 }
37 }
38}
39
40#[derive(Debug, Default)]
45pub struct GainDsp {
46 _sample_rate: f32,
47}
48
49impl Processor for GainDsp {
50 type Params = GainParams;
51
52 fn process(
53 &mut self,
54 buffer: &mut [&mut [f32]],
55 _transport: &Transport,
56 params: &Self::Params,
57 ) {
58 let gain = params.level;
59
60 for channel in buffer.iter_mut() {
61 apply_gain_to_channel(channel, gain);
62 }
63 }
64
65 fn set_sample_rate(&mut self, sample_rate: f32) {
66 self._sample_rate = sample_rate;
67 }
68
69 fn reset(&mut self) {
70 }
72}
73
74#[inline]
75fn apply_gain_to_channel(channel: &mut [f32], gain: f32) {
76 for sample in channel.iter_mut() {
77 *sample *= gain;
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 fn process_with_gain(buffer: &mut [&mut [f32]], level: f32) {
86 let mut processor = GainDsp::default();
87 let params = GainParams { level };
88 let transport = Transport::default();
89 processor.process(buffer, &transport, ¶ms);
90 }
91
92 fn assert_close(actual: f32, expected: f32) {
93 assert!((actual - expected).abs() < 1e-6);
94 }
95
96 #[test]
97 fn test_unity_gain() {
98 let mut left = [0.5, -0.5, 0.25];
99 let mut right = [0.3, -0.3, 0.1];
100 let mut buffer = [&mut left[..], &mut right[..]];
101
102 process_with_gain(&mut buffer, 1.0);
103
104 assert_close(left[0], 0.5);
105 assert_close(left[1], -0.5);
106 assert_close(right[0], 0.3);
107 }
108
109 #[test]
110 fn test_boost() {
111 let mut left = [1.0];
112 let mut buffer = [&mut left[..]];
113
114 process_with_gain(&mut buffer, 2.0);
115
116 assert_close(left[0], 2.0);
117 }
118
119 #[test]
120 fn test_attenuation() {
121 let mut left = [1.0];
122 let mut buffer = [&mut left[..]];
123
124 process_with_gain(&mut buffer, 0.5);
125
126 assert_close(left[0], 0.5);
127 }
128
129 #[test]
130 fn test_param_specs() {
131 let specs = GainParams::param_specs();
132 assert_eq!(specs.len(), 1);
133 assert_eq!(specs[0].name, "Level");
134 assert_eq!(specs[0].id_suffix, "level");
135 assert_eq!(specs[0].default, 1.0);
136 assert_eq!(specs[0].unit, "x");
137 }
138
139 #[test]
140 fn test_from_param_defaults_uses_spec_default() {
141 let defaults = GainParams::from_param_defaults();
142 assert!((defaults.level - 1.0).abs() < 1e-6);
143 }
144}