1use core::any::Any;
4use miniconf::Tree;
5use num_traits::{AsPrimitive, Float, FloatConst};
6use serde::{Deserialize, Serialize, de::DeserializeOwned};
7
8use crate::{
9 Build,
10 iir::{
11 BiquadClamp,
12 coefficients::Shape,
13 pid::{Pid, Units},
14 },
15};
16
17#[derive(Debug, Clone, Tree)]
19#[tree(meta(doc, typename))]
20pub struct Ba<T> {
21 #[tree(with=miniconf::leaf, bounds(serialize="T: Serialize", deserialize="T: DeserializeOwned", any="T: Any"))]
23 pub ba: [[T; 3]; 2],
24 pub u: T,
26 pub min: T,
28 pub max: T,
30}
31
32impl<T: Float> Default for Ba<T> {
33 fn default() -> Self {
34 Self {
35 ba: [[T::zero(); 3], [T::one(), T::zero(), T::zero()]],
36 u: T::zero(),
37 min: T::neg_infinity(),
38 max: T::infinity(),
39 }
40 }
41}
42
43#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, PartialEq, PartialOrd)]
45pub enum Typ {
46 #[default]
48 Lowpass,
49 Highpass,
51 Bandpass,
53 Allpass,
55 Notch,
57 Peaking,
59 Lowshelf,
61 Highshelf,
63 IHo,
65}
66
67#[derive(Clone, Debug, Tree)]
69#[tree(meta(doc, typename))]
70pub struct FilterRepr<T> {
71 #[tree(with=miniconf::leaf)]
73 pub typ: Typ,
74 pub frequency: T,
77 pub gain: T,
79 pub shelf: T,
82 #[tree(with=miniconf::leaf, bounds(serialize="T: Serialize", deserialize="T: DeserializeOwned", any="T: Any"))]
84 pub shape: Shape<T>,
85 pub offset: T,
87 pub min: T,
89 pub max: T,
91}
92
93impl<T: Float + FloatConst> Default for FilterRepr<T> {
94 fn default() -> Self {
95 Self {
96 typ: Typ::default(),
97 frequency: T::zero(),
98 gain: T::one(),
99 shelf: T::one(),
100 shape: Shape::default(),
101 offset: T::zero(),
102 min: T::neg_infinity(),
103 max: T::infinity(),
104 }
105 }
106}
107
108#[derive(
122 Debug,
123 Clone,
124 Tree,
125 strum::AsRefStr,
126 strum::EnumString,
127 strum::EnumDiscriminants,
128 strum::IntoStaticStr,
129)]
130#[strum_discriminants(derive(serde::Serialize, serde::Deserialize), allow(missing_docs))]
131#[tree(meta(doc = "Representation of a biquad", typename))]
132pub enum BiquadRepr<T, C = T, Y = T>
133where
134 Ba<T>: Default,
135 Pid<T>: Default,
136 BiquadClamp<C, Y>: Default,
137 FilterRepr<T>: Default,
138{
139 Ba(Ba<T>),
141 Raw(
143 #[tree(with=miniconf::leaf, bounds(
144 serialize="C: Serialize, Y: Serialize",
145 deserialize="C: DeserializeOwned, Y: DeserializeOwned",
146 any="C: Any, Y: Any"))]
147 BiquadClamp<C, Y>,
148 ),
149 Pid(Pid<T>),
151 Filter(FilterRepr<T>),
153}
154
155impl<T, C, Y> Default for BiquadRepr<T, C, Y>
156where
157 Ba<T>: Default,
158 Pid<T>: Default,
159 BiquadClamp<C, Y>: Default,
160 FilterRepr<T>: Default,
161{
162 fn default() -> Self {
163 Self::Ba(Default::default())
164 }
165}
166
167impl<T, C, Y> BiquadRepr<T, C, Y>
168where
169 BiquadClamp<C, Y>: Default + Clone,
170 Y: 'static + Copy,
171 T: 'static + Float + FloatConst + Default + AsPrimitive<Y>,
172 f32: AsPrimitive<T>,
173 Pid<T>: Build<BiquadClamp<C, Y>, Context = Units<T>>,
174 [[T; 3]; 2]: Into<BiquadClamp<C, Y>>,
175{
176 pub fn build(&self, units: &Units<T>) -> BiquadClamp<C, Y> {
178 let yu = units.y.recip();
179 let yx = units.x * yu;
180 match self {
181 Self::Ba(ba) => {
182 let mut bba = ba.ba;
183 bba[0] = bba[0].map(|b| b * yx);
184 let mut b: BiquadClamp<C, Y> = bba.into();
185 b.u = (ba.u * yu).as_();
186 b.min = (ba.min * yu).as_();
187 b.max = (ba.max * yu).as_();
188 b
189 }
190 Self::Raw(raw) => raw.clone(),
191 Self::Pid(pid) => pid.build(units),
192 Self::Filter(filter) => {
193 let mut f = crate::iir::coefficients::Filter::default();
194 f.gain_db(filter.gain);
195 f.critical_frequency(filter.frequency * units.t);
196 f.shelf_db(filter.shelf);
197 f.set_shape(filter.shape);
198 let mut ba = match filter.typ {
199 Typ::Lowpass => f.lowpass(),
200 Typ::Highpass => f.highpass(),
201 Typ::Allpass => f.allpass(),
202 Typ::Bandpass => f.bandpass(),
203 Typ::Highshelf => f.highshelf(),
204 Typ::Lowshelf => f.lowshelf(),
205 Typ::IHo => f.iho(),
206 Typ::Notch => f.notch(),
207 Typ::Peaking => f.peaking(),
208 };
209 ba[0] = ba[0].map(|b| b * yx);
210 let mut b: BiquadClamp<C, Y> = ba.into();
211 b.u = (filter.offset * yu).as_();
212 b.min = (filter.min * yu).as_();
213 b.max = (filter.max * yu).as_();
214 b
215 }
216 }
217 }
218}