1use std::f32::consts::PI;
2use std::time::Duration;
3
4use crate::Source;
5
6pub fn low_pass<I>(input: I, freq: u32) -> BltFilter<I>
10where
11 I: Source<Item = f32>,
12{
13 BltFilter {
14 input,
15 formula: BltFormula::LowPass { freq, q: 0.5 },
16 applier: None,
17 x_n1: 0.0,
18 x_n2: 0.0,
19 y_n1: 0.0,
20 y_n2: 0.0,
21 }
22}
23
24pub fn high_pass<I>(input: I, freq: u32) -> BltFilter<I>
25where
26 I: Source<Item = f32>,
27{
28 BltFilter {
29 input,
30 formula: BltFormula::HighPass { freq, q: 0.5 },
31 applier: None,
32 x_n1: 0.0,
33 x_n2: 0.0,
34 y_n1: 0.0,
35 y_n2: 0.0,
36 }
37}
38
39#[derive(Clone, Debug)]
40pub struct BltFilter<I> {
41 input: I,
42 formula: BltFormula,
43 applier: Option<BltApplier>,
44 x_n1: f32,
45 x_n2: f32,
46 y_n1: f32,
47 y_n2: f32,
48}
49
50impl<I> BltFilter<I> {
51 pub fn to_low_pass(&mut self, freq: u32) {
53 self.formula = BltFormula::LowPass { freq, q: 0.5 };
54 self.applier = None;
55 }
56
57 pub fn to_high_pass(&mut self, freq: u32) {
59 self.formula = BltFormula::HighPass { freq, q: 0.5 };
60 self.applier = None;
61 }
62
63 #[inline]
65 pub fn inner(&self) -> &I {
66 &self.input
67 }
68
69 #[inline]
71 pub fn inner_mut(&mut self) -> &mut I {
72 &mut self.input
73 }
74
75 #[inline]
77 pub fn into_inner(self) -> I {
78 self.input
79 }
80}
81
82impl<I> Iterator for BltFilter<I>
83where
84 I: Source<Item = f32>,
85{
86 type Item = f32;
87
88 #[inline]
89 fn next(&mut self) -> Option<f32> {
90 let last_in_frame = self.input.current_frame_len() == Some(1);
91
92 if self.applier.is_none() {
93 self.applier = Some(self.formula.to_applier(self.input.sample_rate()));
94 }
95
96 let sample = match self.input.next() {
97 None => return None,
98 Some(s) => s,
99 };
100
101 let result = self
102 .applier
103 .as_ref()
104 .unwrap()
105 .apply(sample, self.x_n1, self.x_n2, self.y_n1, self.y_n2);
106
107 self.y_n2 = self.y_n1;
108 self.x_n2 = self.x_n1;
109 self.y_n1 = result;
110 self.x_n1 = sample;
111
112 if last_in_frame {
113 self.applier = None;
114 }
115
116 Some(result)
117 }
118
119 #[inline]
120 fn size_hint(&self) -> (usize, Option<usize>) {
121 self.input.size_hint()
122 }
123}
124
125impl<I> ExactSizeIterator for BltFilter<I> where I: Source<Item = f32> + ExactSizeIterator {}
126
127impl<I> Source for BltFilter<I>
128where
129 I: Source<Item = f32>,
130{
131 #[inline]
132 fn current_frame_len(&self) -> Option<usize> {
133 self.input.current_frame_len()
134 }
135
136 #[inline]
137 fn channels(&self) -> u16 {
138 self.input.channels()
139 }
140
141 #[inline]
142 fn sample_rate(&self) -> u32 {
143 self.input.sample_rate()
144 }
145
146 #[inline]
147 fn total_duration(&self) -> Option<Duration> {
148 self.input.total_duration()
149 }
150}
151
152#[derive(Clone, Debug)]
153enum BltFormula {
154 LowPass { freq: u32, q: f32 },
155 HighPass { freq: u32, q: f32 },
156}
157
158impl BltFormula {
159 fn to_applier(&self, sampling_frequency: u32) -> BltApplier {
160 match *self {
161 BltFormula::LowPass { freq, q } => {
162 let w0 = 2.0 * PI * freq as f32 / sampling_frequency as f32;
163
164 let alpha = w0.sin() / (2.0 * q);
165 let b1 = 1.0 - w0.cos();
166 let b0 = b1 / 2.0;
167 let b2 = b0;
168 let a0 = 1.0 + alpha;
169 let a1 = -2.0 * w0.cos();
170 let a2 = 1.0 - alpha;
171
172 BltApplier {
173 b0: b0 / a0,
174 b1: b1 / a0,
175 b2: b2 / a0,
176 a1: a1 / a0,
177 a2: a2 / a0,
178 }
179 }
180 BltFormula::HighPass { freq, q } => {
181 let w0 = 2.0 * PI * freq as f32 / sampling_frequency as f32;
182 let cos_w0 = w0.cos();
183 let alpha = w0.sin() / (2.0 * q);
184
185 let b0 = (1.0 + cos_w0) / 2.0;
186 let b1 = -1.0 - cos_w0;
187 let b2 = b0;
188 let a0 = 1.0 + alpha;
189 let a1 = -2.0 * cos_w0;
190 let a2 = 1.0 - alpha;
191
192 BltApplier {
193 b0: b0 / a0,
194 b1: b1 / a0,
195 b2: b2 / a0,
196 a1: a1 / a0,
197 a2: a2 / a0,
198 }
199 }
200 }
201 }
202}
203
204#[derive(Clone, Debug)]
205struct BltApplier {
206 b0: f32,
207 b1: f32,
208 b2: f32,
209 a1: f32,
210 a2: f32,
211}
212
213impl BltApplier {
214 #[inline]
215 fn apply(&self, x_n: f32, x_n1: f32, x_n2: f32, y_n1: f32, y_n2: f32) -> f32 {
216 self.b0 * x_n + self.b1 * x_n1 + self.b2 * x_n2 - self.a1 * y_n1 - self.a2 * y_n2
217 }
218}