diff --git a/crates/threebandeq/Cargo.toml b/crates/threebandeq/Cargo.toml index cc28ad5..10e6409 100644 --- a/crates/threebandeq/Cargo.toml +++ b/crates/threebandeq/Cargo.toml @@ -9,3 +9,5 @@ crate-type = ["cdylib"] [dependencies] baseplug = { git = "https://github.com/wrl/baseplug.git", rev = "9cec68f31cca9c0c7a1448379f75d92bbbc782a8" } serde = "1.0.126" + +utils = { path = "../utils" } diff --git a/crates/threebandeq/src/lib.rs b/crates/threebandeq/src/lib.rs index bb06c05..52989bd 100644 --- a/crates/threebandeq/src/lib.rs +++ b/crates/threebandeq/src/lib.rs @@ -6,13 +6,15 @@ use baseplug::{Plugin, ProcessContext}; use serde::{Deserialize, Serialize}; +use utils::threeband::*; + baseplug::model! { #[derive(Debug, Serialize, Deserialize)] struct ThreeBandEqModel { - #[model(min = 0.0, max = 48000.0)] + #[model(min = 0.0, max = 15000.0)] #[parameter(name = "low band")] low_band: f32, - #[model(min = 0.0, max = 48000.0)] + #[model(min = 0.0, max = 15000.0)] #[parameter(name = "mid band")] high_band: f32, @@ -42,27 +44,10 @@ impl Default for ThreeBandEqModel { } #[derive(Default)] -struct Eq { - // Filter #1 (Low band) - f1p0: f32, // Poles ... - f1p1: f32, - f1p2: f32, - f1p3: f32, - - // Filter #2 (High band) - f2p0: f32, // Poles ... - f2p1: f32, - f2p2: f32, - f2p3: f32, - - // Sample history buffer - sdm1: f32, // Sample data minus 1 - sdm2: f32, // 2 - sdm3: f32, // 3 -} +struct Eq(ThreeBandSplitter); impl Eq { #[allow(clippy::too_many_arguments)] - fn process( + pub fn process( &mut self, input: f32, lf: f32, @@ -72,40 +57,9 @@ impl Eq { hg: f32, sample_rate: f32, ) -> f32 { - let lf = 2.0 * (std::f32::consts::PI * (lf / sample_rate)).sin(); - let hf = 2.0 * (std::f32::consts::PI * (hf / sample_rate)).sin(); + let (l, m, h) = self.0.process(input, lf, hf, sample_rate); - // Filter #1 (lowpass) - self.f1p0 += lf * (input - self.f1p0) + VSA; - self.f1p1 += lf * (self.f1p0 - self.f1p1); - self.f1p2 += lf * (self.f1p1 - self.f1p2); - self.f1p3 += lf * (self.f1p2 - self.f1p3); - - let l = self.f1p3; - - // Filter #2 (highpass) - self.f2p0 += hf * (input - self.f2p0) + VSA; - self.f2p1 += hf * (self.f2p0 - self.f2p1); - self.f2p2 += hf * (self.f2p1 - self.f2p2); - self.f2p3 += hf * (self.f2p2 - self.f2p3); - - // we subtract from sdm3 because the filter has a three sample delay - let h = self.sdm3 - self.f2p3; - - // Calculate midrange (signal - (low + high)) - let m = self.sdm3 - (h + l); - - // Scale - let l = l * lg; - let m = m * mg; - let h = h * hg; - - // Shuffle history buffer - self.sdm3 = self.sdm2; - self.sdm2 = self.sdm1; - self.sdm1 = input; - - l + m + h + l * lg + m * mg + h * hg } } @@ -115,12 +69,9 @@ struct ThreeBandEq { r_eq: Eq, } -/// Very small amount -const VSA: f32 = 1.0 / 4294967295.0; - impl Plugin for ThreeBandEq { - const NAME: &'static str = "basic gain"; - const PRODUCT: &'static str = "basic gain"; + const NAME: &'static str = "threebandeq"; + const PRODUCT: &'static str = "threebandeq"; const VENDOR: &'static str = "unnieversal"; const INPUT_CHANNELS: usize = 2; diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index c5ccea0..2e4ec2b 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -1,3 +1,4 @@ pub mod buffers; pub mod logs; pub mod pitch; +pub mod threeband; diff --git a/crates/utils/src/threeband.rs b/crates/utils/src/threeband.rs new file mode 100644 index 0000000..1e7832e --- /dev/null +++ b/crates/utils/src/threeband.rs @@ -0,0 +1,57 @@ +/// Very small amount +const VSA: f32 = 1.0 / 4294967295.0; + +/// Splits the input into three bands +#[derive(Default)] +pub struct ThreeBandSplitter { + // Filter #1 (Low band) + f1p0: f32, // Poles ... + f1p1: f32, + f1p2: f32, + f1p3: f32, + + // Filter #2 (High band) + f2p0: f32, // Poles ... + f2p1: f32, + f2p2: f32, + f2p3: f32, + + // Sample history buffer + sdm1: f32, // Sample data minus 1 + sdm2: f32, // 2 + sdm3: f32, // 3 +} +impl ThreeBandSplitter { + /// Returns (low, mid, high) bands + pub fn process(&mut self, input: f32, lf: f32, hf: f32, sample_rate: f32) -> (f32, f32, f32) { + let lf = 2.0 * (std::f32::consts::PI * (lf / sample_rate)).sin(); + let hf = 2.0 * (std::f32::consts::PI * (hf / sample_rate)).sin(); + + // Filter #1 (low pass) + self.f1p0 += lf * (input - self.f1p0) + VSA; + self.f1p1 += lf * (self.f1p0 - self.f1p1); + self.f1p2 += lf * (self.f1p1 - self.f1p2); + self.f1p3 += lf * (self.f1p2 - self.f1p3); + + let l = self.f1p3; + + // Filter #2 (high pass) + self.f2p0 += hf * (input - self.f2p0) + VSA; + self.f2p1 += hf * (self.f2p0 - self.f2p1); + self.f2p2 += hf * (self.f2p1 - self.f2p2); + self.f2p3 += hf * (self.f2p2 - self.f2p3); + + // we subtract from sdm3 because the filter has a three sample delay + let h = self.sdm3 - self.f2p3; + + // Calculate midrange (signal - (low + high)) + let m = self.sdm3 - (h + l); + + // Shuffle history buffer + self.sdm3 = self.sdm2; + self.sdm2 = self.sdm1; + self.sdm1 = input; + + (l, m, h) + } +}