1use crate::eq::plotter;
2use scales::prelude::*;
3
4pub type Frequency = f64;
5pub type Gain = f64;
6pub type Q = f64;
7pub type Slope = usize;
8pub type Active = bool;
9
10pub type X = f64;
11pub type Y = f64;
12pub type Radius = f64;
13
14#[derive(Debug, PartialEq, Clone)]
15pub struct EQ {
16 pub bands: Vec<(EqBand, Active)>,
17 pub min_gain: Gain,
18 pub max_gain: Gain,
19 pub min_frequency: Frequency,
20 pub max_frequency: Frequency,
21 pub min_q: Q,
22 pub max_q: Q,
23 pub active: Active,
24}
25
26impl EQ {
27 pub fn new(
28 bands: Vec<(EqBand, Active)>,
29 min_gain: f64,
30 max_gain: f64,
31 min_frequency: f64,
32 max_frequency: f64,
33 min_q: f64,
34 max_q: f64,
35 active: Active,
36 ) -> EQ {
37 EQ {
38 bands,
39 min_gain,
40 max_gain,
41 min_frequency,
42 max_frequency,
43 min_q,
44 max_q,
45 active,
46 }
47 }
48
49 pub fn plot(&self, width: f64, height: f64, invert_y: bool) -> EqGraph {
50 plotter::plot_eq(self, width, height, invert_y)
51 }
52
53 pub fn calc_major_frequency_grid_markers(&self, width: f64) -> Vec<X> {
54 let x_conv = self.x_to_frequency_converter(width);
55
56 let exp_start = self.min_frequency.log10().floor() as i32;
57 let exp_end = self.max_frequency.log10().ceil() as i32;
58 let mut out = Vec::new();
59 for exp in exp_start..exp_end {
60 let f = 10f64.powi(exp);
61 if self.min_frequency < f && f < self.max_frequency {
62 let x = x_conv.convert_back(f);
63 out.push(x);
64 }
65 }
66
67 out
68 }
69
70 pub fn calc_minor_frequency_grid_markers(&self, width: f64) -> Vec<X> {
71 let x_conv = self.x_to_frequency_converter(width);
72
73 let exp_start = self.min_frequency.log10().floor() as i32;
74 let exp_end = self.max_frequency.log10().ceil() as i32;
75 let mut out = Vec::new();
76 for exp in exp_start..exp_end {
77 for factor in 2..10 {
78 let f = factor as f64 * 10f64.powi(exp);
79 if self.min_frequency < f && f < self.max_frequency {
80 let x = x_conv.convert_back(f);
81 out.push(x);
82 }
83 }
84 }
85
86 out
87 }
88
89 pub fn update(&mut self, index: usize, change: Parameter) {
90 if index >= self.bands.len() {
91 return;
92 }
93
94 let band = self.bands[index].to_owned();
95 if let Some(new_band) = update_band(band.clone(), change) {
96 self.bands
97 .splice(index..index + 1, std::iter::once(new_band));
98 }
99 }
100
101 pub fn x_to_frequency_converter(
102 &self,
103 width: f64,
104 ) -> (LinearScale<f64>, LogarithmicScale<f64>) {
105 let x_scale = LinearScale::new(0.0, width as f64);
106 let freq_scale = LogarithmicScale::new(self.min_frequency, self.max_frequency);
107 (x_scale, freq_scale)
108 }
109
110 pub fn y_to_gain_converter(
111 &self,
112 height: f64,
113 inverted: bool,
114 ) -> (LinearScale<f64>, LinearScale<f64>) {
115 let y_scale = if inverted {
116 LinearScale::inverted(0.0, height as f64)
117 } else {
118 LinearScale::new(0.0, height as f64)
119 };
120 let gain_scale = LinearScale::new(self.min_gain, self.max_gain);
121 (y_scale, gain_scale)
122 }
123
124 pub fn q_to_radius_converter(
125 &self,
126 width: f64,
127 ) -> (LogarithmicScale<f64>, LogarithmicScale<f64>) {
128 let q_scale = LogarithmicScale::new(self.min_q, self.max_q);
129 let radius_scale = LogarithmicScale::inverted(width / 60.0, width / 15.0);
130 (q_scale, radius_scale)
131 }
132}
133
134impl Default for EQ {
135 fn default() -> Self {
136 let mut bands = Vec::new();
137 bands.push((
138 EqBand::HighPass {
139 frequency: 100.0,
140 slope: 12,
141 },
142 true,
143 ));
144 bands.push((
145 EqBand::Bell {
146 frequency: 400.0,
147 gain: 0.0,
148 q: 1.0,
149 },
150 true,
151 ));
152 bands.push((
153 EqBand::Bell {
154 frequency: 1_000.0,
155 gain: 0.0,
156 q: 1.0,
157 },
158 true,
159 ));
160 bands.push((
161 EqBand::HighShelf {
162 frequency: 4_000.0,
163 gain: 0.0,
164 },
165 true,
166 ));
167
168 let min_gain = -12.0;
169 let max_gain = 12.0;
170 let min_frequency = 20.0;
171 let max_frequency = 24_000.0;
172 let min_q = 0.1;
173 let max_q = 100.0;
174 let active = true;
175
176 EQ {
177 bands,
178 min_gain,
179 max_gain,
180 min_frequency,
181 max_frequency,
182 min_q,
183 max_q,
184 active,
185 }
186 }
187}
188
189#[derive(Debug, PartialEq, Clone)]
190pub enum EqBand {
191 Bell {
192 frequency: Frequency,
193 gain: Gain,
194 q: Q,
195 },
196 HighShelf {
197 frequency: Frequency,
198 gain: Gain,
199 },
200 LowShelf {
201 frequency: Frequency,
202 gain: Gain,
203 },
204 HighPass {
205 frequency: Frequency,
206 slope: Slope,
207 },
208 LowPass {
209 frequency: Frequency,
210 slope: Slope,
211 },
212}
213
214impl EqBand {
215 pub fn plot(
216 &self,
217 range: impl Iterator<Item = Frequency> + 'static,
218 ) -> Box<dyn Iterator<Item = (Frequency, Gain)>> {
219 plotter::plot(self, range)
220 }
221
222 pub fn frequency(&self) -> Frequency {
223 match self {
224 EqBand::Bell { frequency, .. } => *frequency,
225 EqBand::HighShelf { frequency, .. } => *frequency,
226 EqBand::LowShelf { frequency, .. } => *frequency,
227 EqBand::HighPass { frequency, .. } => *frequency,
228 EqBand::LowPass { frequency, .. } => *frequency,
229 }
230 }
231
232 pub fn gain(&self) -> Option<Gain> {
233 match self {
234 EqBand::Bell { gain, .. } => Some(*gain),
235 EqBand::HighShelf { gain, .. } => Some(*gain),
236 EqBand::LowShelf { gain, .. } => Some(*gain),
237 EqBand::HighPass { .. } => None,
238 EqBand::LowPass { .. } => None,
239 }
240 }
241
242 pub fn q(&self) -> Option<Q> {
243 if let EqBand::Bell { q, .. } = self {
244 Some(*q)
245 } else {
246 None
247 }
248 }
249}
250
251#[derive(Debug, Clone, PartialEq)]
252pub enum Parameter {
253 Frequency(f64),
254 Gain(f64),
255 Q(f64),
256 Slope(usize),
257 Active(bool),
258}
259
260pub struct EqGraph {
261 pub band_curves: Vec<(Vec<(X, Y)>, Active)>,
262 pub sum: Vec<(X, Y)>,
263}
264
265fn update_band(band: (EqBand, bool), change: Parameter) -> Option<(EqBand, bool)> {
266 match (band, change) {
267 ((EqBand::Bell { gain, q, .. }, active), Parameter::Frequency(frequency)) => {
268 Some((EqBand::Bell { frequency, gain, q }, active))
269 }
270 ((EqBand::Bell { frequency, q, .. }, active), Parameter::Gain(gain)) => {
271 Some((EqBand::Bell { frequency, gain, q }, active))
272 }
273 (
274 (
275 EqBand::Bell {
276 frequency, gain, ..
277 },
278 active,
279 ),
280 Parameter::Q(q),
281 ) => Some((EqBand::Bell { frequency, gain, q }, active)),
282 ((EqBand::HighShelf { gain, .. }, active), Parameter::Frequency(frequency)) => {
283 Some((EqBand::HighShelf { frequency, gain }, active))
284 }
285 ((EqBand::HighShelf { frequency, .. }, active), Parameter::Gain(gain)) => {
286 Some((EqBand::HighShelf { frequency, gain }, active))
287 }
288 ((EqBand::LowShelf { gain, .. }, active), Parameter::Frequency(frequency)) => {
289 Some((EqBand::LowShelf { frequency, gain }, active))
290 }
291 ((EqBand::LowShelf { frequency, .. }, active), Parameter::Gain(gain)) => {
292 Some((EqBand::LowShelf { frequency, gain }, active))
293 }
294 ((EqBand::HighPass { slope, .. }, active), Parameter::Frequency(frequency)) => {
295 Some((EqBand::HighPass { frequency, slope }, active))
296 }
297 ((EqBand::HighPass { frequency, .. }, active), Parameter::Slope(slope)) => {
298 Some((EqBand::HighPass { frequency, slope }, active))
299 }
300 ((EqBand::LowPass { slope, .. }, active), Parameter::Frequency(frequency)) => {
301 Some((EqBand::LowPass { frequency, slope }, active))
302 }
303 ((EqBand::LowPass { frequency, .. }, active), Parameter::Slope(slope)) => {
304 Some((EqBand::LowPass { frequency, slope }, active))
305 }
306 ((band, _), Parameter::Active(active)) => Some((band, active)),
307 _ => None,
308 }
309}