caw_modules/
low_pass_butterworth.rs1use crate::low_level::biquad_filter::butterworth;
2use caw_builder_proc_macros::builder;
3use caw_core::{Buf, Filter, SigCtx, SigT};
4use itertools::izip;
5
6builder! {
7 #[constructor = "low_pass_butterworth"]
8 #[constructor_doc = "A basic low pass filter"]
9 #[generic_setter_type_name = "X"]
10 pub struct Props {
11 #[generic_with_constraint = "SigT<Item = f32>"]
12 #[generic_name = "C"]
13 cutoff_hz: _,
14 #[default = 1]
15 filter_order_half: usize,
16 }
17}
18
19impl<C> Filter for Props<C>
20where
21 C: SigT<Item = f32>,
22{
23 type ItemIn = f32;
24
25 type Out<S>
26 = LowPassButterworth<S, C>
27 where
28 S: SigT<Item = Self::ItemIn>;
29
30 fn into_sig<S>(self, sig: S) -> Self::Out<S>
31 where
32 S: SigT<Item = Self::ItemIn>,
33 {
34 LowPassButterworth {
35 state: butterworth::State::new(self.filter_order_half),
36 props: self,
37 sig,
38 buf: Vec::new(),
39 }
40 }
41}
42
43pub struct LowPassButterworth<S, C>
44where
45 S: SigT<Item = f32>,
46 C: SigT<Item = f32>,
47{
48 props: Props<C>,
49 sig: S,
50 state: butterworth::State,
51 buf: Vec<f32>,
52}
53
54impl<S, C> SigT for LowPassButterworth<S, C>
55where
56 S: SigT<Item = f32>,
57 C: SigT<Item = f32>,
58{
59 type Item = f32;
60
61 fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
62 self.buf.resize(ctx.num_samples, 0.0);
63 let sig = self.sig.sample(ctx);
64 let cutoff_hz = self.props.cutoff_hz.sample(ctx);
65 for (out, sample, cutoff_hz) in izip! {
66 self.buf.iter_mut(),
67 sig.iter(),
68 cutoff_hz.iter(),
69 } {
70 *out = butterworth::low_pass::run(
71 &mut self.state,
72 sample as f64,
73 ctx.sample_rate_hz as f64,
74 cutoff_hz as f64,
75 ) as f32;
76 }
77 &self.buf
78 }
79}