1use core::any::Any;
2use miniconf::Tree;
3use num_traits::{AsPrimitive, Float, FloatConst};
4use serde::{Deserialize, Serialize};
5
6use crate::{
7 Coefficient,
8 iir::{Biquad, Pid, Shape},
9};
10
11#[derive(Debug, Clone, Tree)]
13#[tree(meta(doc, typename))]
14pub struct Ba<T> {
15 #[tree(with=miniconf::leaf, bounds(serialize="T: Serialize", deserialize="T: Deserialize<'de>", any="T: Any"))]
17 pub ba: [[T; 3]; 2],
18 pub u: T,
20 pub min: T,
22 pub max: T,
24}
25
26impl<T: Float> Default for Ba<T> {
27 fn default() -> Self {
28 Self {
29 ba: [[T::zero(); 3], [T::one(), T::zero(), T::zero()]],
30 u: T::zero(),
31 min: T::neg_infinity(),
32 max: 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)]
63#[tree(meta(doc, typename))]
64pub struct FilterRepr<T> {
65 #[tree(with=miniconf::leaf)]
67 typ: Typ,
68 frequency: T,
71 gain: T,
73 shelf: T,
76 #[tree(with=miniconf::leaf, bounds(serialize="T: Serialize", deserialize="T: Deserialize<'de>", any="T: Any"))]
78 shape: Shape<T>,
79 offset: T,
81 min: T,
83 max: T,
85}
86
87impl<T: Float + FloatConst> Default for FilterRepr<T> {
88 fn default() -> Self {
89 Self {
90 typ: Typ::default(),
91 frequency: T::zero(),
92 gain: T::one(),
93 shelf: T::one(),
94 shape: Shape::default(),
95 offset: T::zero(),
96 min: T::neg_infinity(),
97 max: T::infinity(),
98 }
99 }
100}
101
102#[derive(
116 Debug,
117 Clone,
118 Tree,
119 strum::EnumString,
120 strum::AsRefStr,
121 strum::FromRepr,
122 strum::EnumDiscriminants,
123 strum::IntoStaticStr,
124)]
125#[strum_discriminants(derive(serde::Serialize, serde::Deserialize), allow(missing_docs))]
126#[tree(meta(doc = "Representation of Biquad", typename))]
127pub enum BiquadRepr<T, C>
128where
129 C: Coefficient,
130 T: Float + FloatConst,
131{
132 Ba(Ba<T>),
134 Raw(
136 #[tree(with=miniconf::leaf, bounds(serialize="C: Serialize", deserialize="C: Deserialize<'de>", any="C: Any"))]
137 Biquad<C>,
138 ),
139 Pid(Pid<T>),
141 Filter(FilterRepr<T>),
143}
144
145impl<T, C> Default for BiquadRepr<T, C>
146where
147 C: Coefficient,
148 T: Float + FloatConst,
149{
150 fn default() -> Self {
151 Self::Ba(Default::default())
152 }
153}
154
155impl<T, C> BiquadRepr<T, C>
156where
157 C: Coefficient + AsPrimitive<C> + AsPrimitive<T>,
158 T: AsPrimitive<C> + Float + FloatConst,
159{
160 pub fn build<I>(&self, period: T, b_scale: T, y_scale: T) -> Biquad<C>
172 where
173 T: AsPrimitive<I>,
174 I: Float + AsPrimitive<C>,
175 C: AsPrimitive<I>,
176 f32: AsPrimitive<T>,
177 {
178 match self {
179 Self::Ba(ba) => {
180 let mut b = Biquad::from(&[ba.ba[0].map(|b| b * b_scale), ba.ba[1]]);
181 b.set_u((ba.u * y_scale).as_());
182 b.set_min((ba.min * y_scale).as_());
183 b.set_max((ba.max * y_scale).as_());
184 b
185 }
186 Self::Raw(raw) => raw.clone(),
187 Self::Pid(pid) => pid.build::<_, I>(period, b_scale, y_scale),
188 Self::Filter(filter) => {
189 let mut f = crate::iir::Filter::default();
190 f.gain_db(filter.gain);
191 f.critical_frequency(filter.frequency * period);
192 f.shelf_db(filter.shelf);
193 f.set_shape(filter.shape);
194 let mut ba = match filter.typ {
195 Typ::Lowpass => f.lowpass(),
196 Typ::Highpass => f.highpass(),
197 Typ::Allpass => f.allpass(),
198 Typ::Bandpass => f.bandpass(),
199 Typ::Highshelf => f.highshelf(),
200 Typ::Lowshelf => f.lowshelf(),
201 Typ::IHo => f.iho(),
202 Typ::Notch => f.notch(),
203 Typ::Peaking => f.peaking(),
204 };
205 ba[0] = ba[0].map(|b| b * b_scale);
206 let mut b = Biquad::from(&ba);
207 b.set_u((filter.offset * y_scale).as_());
208 b.set_min((filter.min * y_scale).as_());
209 b.set_max((filter.max * y_scale).as_());
210 b
211 }
212 }
213 }
214}