1use miniconf::{Leaf, Tree};
2use num_traits::{AsPrimitive, Float, FloatConst};
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 iir::{Biquad, Pid, Shape},
7 Coefficient,
8};
9
10#[derive(Debug, Clone, Tree)]
12pub struct Ba<T> {
13 pub ba: Leaf<[[T; 3]; 2]>,
15 pub u: Leaf<T>,
17 pub min: Leaf<T>,
19 pub max: Leaf<T>,
21}
22
23impl<T> Default for Ba<T>
24where
25 T: Float,
26{
27 fn default() -> Self {
28 Self {
29 ba: Leaf([[T::zero(); 3], [T::one(), T::zero(), T::zero()]]),
30 u: Leaf(T::zero()),
31 min: Leaf(T::neg_infinity()),
32 max: Leaf(T::infinity()),
33 }
34 }
35}
36
37#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, PartialEq, PartialOrd)]
39pub enum Typ {
40 #[default]
42 Lowpass,
43 Highpass,
45 Bandpass,
47 Allpass,
49 Notch,
51 Peaking,
53 Lowshelf,
55 Highshelf,
57 IHo,
59}
60
61#[derive(Clone, Debug, Tree)]
63pub struct FilterRepr<T> {
64 typ: Leaf<Typ>,
66 frequency: Leaf<T>,
69 gain: Leaf<T>,
71 shelf: Leaf<T>,
74 shape: Leaf<Shape<T>>,
76 offset: Leaf<T>,
78 min: Leaf<T>,
80 max: Leaf<T>,
82}
83
84impl<T: Float + FloatConst> Default for FilterRepr<T> {
85 fn default() -> Self {
86 Self {
87 typ: Leaf(Typ::default()),
88 frequency: Leaf(T::zero()),
89 gain: Leaf(T::one()),
90 shelf: Leaf(T::one()),
91 shape: Leaf(Shape::default()),
92 offset: Leaf(T::zero()),
93 min: Leaf(T::neg_infinity()),
94 max: Leaf(T::infinity()),
95 }
96 }
97}
98
99#[derive(
101 Debug,
102 Clone,
103 Tree,
104 strum::EnumString,
105 strum::AsRefStr,
106 strum::FromRepr,
107 strum::EnumDiscriminants,
108)]
109#[strum_discriminants(derive(serde::Serialize, serde::Deserialize))]
110pub enum BiquadRepr<T, C>
111where
112 C: Coefficient,
113 T: Float + FloatConst,
114{
115 Ba(Ba<T>),
117 Raw(Leaf<Biquad<C>>),
119 Pid(Pid<T>),
121 Filter(FilterRepr<T>),
123}
124
125impl<T, C> BiquadRepr<T, C>
126where
127 C: Coefficient,
128 T: Float + FloatConst,
129{
130 pub fn tag_serialize<K: miniconf::Keys, S: serde::Serializer>(
142 &self,
143 keys: K,
144 ser: S,
145 ) -> Result<S::Ok, miniconf::Error<S::Error>> {
146 miniconf::TreeSerialize::serialize_by_key(
147 &Leaf(BiquadReprDiscriminants::from(self)),
148 keys,
149 ser,
150 )
151 }
152
153 pub fn tag_deserialize<'de, K: miniconf::Keys, D: serde::Deserializer<'de>>(
155 &mut self,
156 keys: K,
157 de: D,
158 ) -> Result<(), miniconf::Error<D::Error>> {
159 let mut v = Leaf(BiquadReprDiscriminants::from(&*self));
160 miniconf::TreeDeserialize::deserialize_by_key(&mut v, keys, de)?;
161 *self = BiquadRepr::from_repr(*v as _).unwrap();
162 Ok(())
163 }
164}
165
166impl<T, C> Default for BiquadRepr<T, C>
167where
168 C: Coefficient,
169 T: Float + FloatConst,
170{
171 fn default() -> Self {
172 Self::Ba(Default::default())
173 }
174}
175
176impl<T, C> BiquadRepr<T, C>
177where
178 C: Coefficient + AsPrimitive<C> + AsPrimitive<T>,
179 T: AsPrimitive<C> + Float + FloatConst,
180{
181 pub fn build<I>(&self, period: T, b_scale: T, y_scale: T) -> Biquad<C>
193 where
194 T: AsPrimitive<I>,
195 I: Float + 'static + AsPrimitive<C>,
196 C: AsPrimitive<I>,
197 f32: AsPrimitive<T>,
198 {
199 match self {
200 Self::Ba(ba) => {
201 let mut b = Biquad::from(&[ba.ba[0].map(|b| b * b_scale), ba.ba[1]]);
202 b.set_u((*ba.u * y_scale).as_());
203 b.set_min((*ba.min * y_scale).as_());
204 b.set_max((*ba.max * y_scale).as_());
205 b
206 }
207 Self::Raw(Leaf(raw)) => raw.clone(),
208 Self::Pid(pid) => pid.build::<_, I>(period, b_scale, y_scale),
209 Self::Filter(filter) => {
210 let mut f = crate::iir::Filter::default();
211 f.gain_db(*filter.gain);
212 f.critical_frequency(*filter.frequency * period);
213 f.shelf_db(*filter.shelf);
214 f.set_shape(*filter.shape);
215 let mut ba = match *filter.typ {
216 Typ::Lowpass => f.lowpass(),
217 Typ::Highpass => f.highpass(),
218 Typ::Allpass => f.allpass(),
219 Typ::Bandpass => f.bandpass(),
220 Typ::Highshelf => f.highshelf(),
221 Typ::Lowshelf => f.lowshelf(),
222 Typ::IHo => f.iho(),
223 Typ::Notch => f.notch(),
224 Typ::Peaking => f.peaking(),
225 };
226 ba[0] = ba[0].map(|b| b * b_scale);
227 let mut b = Biquad::from(&ba);
228 b.set_u((*filter.offset * y_scale).as_());
229 b.set_min((*filter.min * y_scale).as_());
230 b.set_max((*filter.max * y_scale).as_());
231 b
232 }
233 }
234 }
235}