1use std::collections::VecDeque;
9
10use crate::{Float, Sample};
11
12pub trait Clamp {
16 #[must_use]
18 fn clamp(&self, mi: Self, mx: Self) -> Self;
19}
20impl Clamp for Float {
21 fn clamp(&self, mi: Float, mx: Float) -> Self {
22 Float::clamp(*self as Float, mi, mx)
23 }
24}
25
26pub trait Filter<T: Sample>: Send {
30 fn filter(&mut self, input: T) -> T;
32
33 fn fill(&mut self, s: T);
35}
36
37pub trait ClampedFilter<T: Sample + Clamp>: Filter<T> {
42 fn filter_clamped(&mut self, input: T, mi: T, mx: T) -> T;
44}
45
46pub struct IirFilter<T: Sample> {
56 taps: Vec<T>,
57 buf: VecDeque<T>,
58}
59
60impl<T> IirFilter<T>
61where
62 T: Sample + std::ops::Mul<T, Output = T> + std::ops::Add<T, Output = T>,
63{
64 pub fn new(taps: &[T]) -> Self {
66 Self {
67 taps: taps.to_vec(),
68 buf: VecDeque::new(),
69 }
70 }
71}
72
73impl<T> Filter<T> for IirFilter<T>
74where
75 T: Sample
76 + std::ops::Mul<T, Output = T>
77 + std::ops::Add<T, Output = T>
78 + Send
79 + std::fmt::Debug,
80{
81 fn filter(&mut self, sample: T) -> T {
82 let mut ret = self.taps[0] * sample;
83 for (i, s) in self.buf.iter().rev().enumerate() {
84 ret = ret + *s * self.taps[i + 1];
85 }
86 self.buf.push_back(ret);
87 if self.buf.len() == self.taps.len() {
88 self.buf.pop_front();
89 }
90 ret
91 }
92
93 fn fill(&mut self, s: T) {
94 for _ in 0..(self.taps.len() - 1) {
95 self.buf.push_back(s);
96 }
97 }
98}
99
100impl<T> ClampedFilter<T> for IirFilter<T>
101where
102 T: Sample
103 + std::ops::Mul<T, Output = T>
104 + std::ops::Add<T, Output = T>
105 + Clamp
106 + Send
107 + std::fmt::Debug,
108{
109 fn filter_clamped(&mut self, sample: T, mi: T, mx: T) -> T {
110 let mut ret = self.taps[0] * sample;
111 for (i, s) in self.buf.iter().rev().enumerate() {
112 ret = ret + *s * self.taps[i + 1];
113 }
114 ret = ret.clamp(mi, mx);
115 self.buf.push_back(ret);
116 if self.buf.len() == self.taps.len() {
117 self.buf.pop_front();
118 }
119 ret
120 }
121}
122
123#[cfg(test)]
124#[cfg_attr(coverage_nightly, coverage(off))]
125mod tests {
126 use super::*;
127 use crate::Result;
128
129 #[test]
130 fn zero_pole() -> Result<()> {
131 let mut f = IirFilter::new(&[1.0]);
132 assert_eq!(f.filter(123.0), 123.0);
133 assert_eq!(f.filter(123.0), 123.0);
134 let mut f = IirFilter::new(&[-0.5]);
135 assert_eq!(f.filter(402.0), -201.0);
136 assert_eq!(f.filter(402.0), -201.0);
137 Ok(())
138 }
139
140 #[test]
141 fn single_pole() -> Result<()> {
142 let mut f = IirFilter::new(&[1.0, 0.0]);
143 assert_eq!(f.filter(10.0), 10.0);
144 assert_eq!(f.filter(10.0), 10.0);
145 assert_eq!(f.filter(10.0), 10.0);
146
147 let mut f = IirFilter::new(&[0.9f32, 0.1]);
148 assert_eq!(f.filter(100.0), 90.0);
149 assert_eq!(f.filter(100.0), 99.0);
150 assert_eq!(f.filter(100.0), 99.9);
151 assert!((f.filter(100.0) - 99.99).abs() < 0.00001);
152
153 Ok(())
154 }
155
156 #[test]
157 fn single_pole_clamped() -> Result<()> {
158 let mut f = IirFilter::new(&[1.0, 0.0]);
159 assert_eq!(f.filter_clamped(10.0, 0.0, 1.0), 1.0);
160 assert_eq!(f.filter_clamped(10.0, 0.0, 1.0), 1.0);
161 assert_eq!(f.filter_clamped(10.0, 0.0, 1.0), 1.0);
162
163 Ok(())
164 }
165
166 #[test]
167 fn multi_pole() -> Result<()> {
168 let mut f = IirFilter::new(&[1.0, 0.0, 0.0]);
169 assert_eq!(f.filter(10.0), 10.0);
170 assert_eq!(f.filter(10.0), 10.0);
171 assert_eq!(f.filter(10.0), 10.0);
172 assert_eq!(f.filter(10.0), 10.0);
173
174 let mut f = IirFilter::new(&[1.0f32, 0.9, 0.1]);
175 assert_eq!(f.filter(100.0), 100.0);
176 assert_eq!(f.filter(100.0), 190.0);
177 assert_eq!(f.filter(100.0), 281.0);
178 assert_eq!(f.filter(100.0), 371.9);
179
180 Ok(())
181 }
182
183 #[test]
184 fn filled() -> Result<()> {
185 let mut f = IirFilter::new(&[1.0f32, 0.9, 0.1]);
186 f.fill(100.0);
187 assert_eq!(f.filter(100.0), 200.0);
188 assert_eq!(f.filter(100.0), 290.0);
189 assert_eq!(f.filter(200.0), 481.0);
190 Ok(())
191 }
192}