[threebandeq] implement everything

main
annieversary 2021-07-24 22:07:45 +02:00
parent d6dbfe2321
commit c7c1b13cb3
2 changed files with 126 additions and 14 deletions

View File

@ -54,7 +54,7 @@ the following is the current list of plugins
- multidim: randomized midi note generator - multidim: randomized midi note generator
- robotuna: automatic pitch correction - robotuna: automatic pitch correction
- hysteria: hysteresis nonlinear effect - hysteria: hysteresis nonlinear effect
- threebandeq: [WIP] 3 band eq - threebandeq: 3 band eq
### basic_gain ### basic_gain
@ -134,7 +134,16 @@ turn the values up for loud and distorted. don't set them all to the max at once
### threebandeq [WIP] ### threebandeq [WIP]
wip, there's nothing yet simple three band equalizer
parameters:
- `low band`: frequency at which the low band ends
- `high band`: frequency at which the high band starts
- `low gain`: gain for the low band
- `mid gain`: gain for the mid band
- `high gain`: gain for the high band
low band goes from 0hz to `low band`, mid band goes from `low band` to `high band`, high band goes from `high band` to half the sample rate
## contributing ## contributing

View File

@ -1,31 +1,122 @@
#![allow(incomplete_features)] #![allow(incomplete_features)]
#![feature(generic_associated_types)] #![feature(generic_associated_types)]
// https://www.musicdsp.org/en/latest/Filters/236-3-band-equaliser.html
use baseplug::{Plugin, ProcessContext}; use baseplug::{Plugin, ProcessContext};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
baseplug::model! { baseplug::model! {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct ThreeBandEqModel { struct ThreeBandEqModel {
#[model(min = -90.0, max = 3.0)] #[model(min = 0.0, max = 48000.0)]
#[parameter(name = "gain", unit = "Decibels", #[parameter(name = "low band")]
gradient = "Power(0.15)")] low_band: f32,
gain: f32 #[model(min = 0.0, max = 48000.0)]
#[parameter(name = "mid band")]
high_band: f32,
#[model(min = 0.0, max = 3.0)]
#[parameter(name = "low gain")]
low_gain: f32,
#[model(min = 0.0, max = 3.0)]
#[parameter(name = "mid gain")]
mid_gain: f32,
#[model(min = 0.0, max = 3.0)]
#[parameter(name = "high gain")]
high_gain: f32,
} }
} }
impl Default for ThreeBandEqModel { impl Default for ThreeBandEqModel {
fn default() -> Self { fn default() -> Self {
Self { Self {
// "gain" is converted from dB to coefficient in the parameter handling code, low_band: 800.0,
// so in the model here it's a coeff. high_band: 5000.0,
// -0dB == 1.0
gain: 1.0, low_gain: 1.0,
mid_gain: 1.0,
high_gain: 1.0,
} }
} }
} }
struct ThreeBandEq; #[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
}
impl Eq {
#[allow(clippy::too_many_arguments)]
fn process(
&mut self,
input: f32,
lf: f32,
hf: f32,
lg: f32,
mg: f32,
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();
// 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
}
}
#[derive(Default)]
struct ThreeBandEq {
l_eq: Eq,
r_eq: Eq,
}
/// Very small amount
const VSA: f32 = 1.0 / 4294967295.0;
impl Plugin for ThreeBandEq { impl Plugin for ThreeBandEq {
const NAME: &'static str = "basic gain"; const NAME: &'static str = "basic gain";
@ -39,7 +130,8 @@ impl Plugin for ThreeBandEq {
#[inline] #[inline]
fn new(_sample_rate: f32, _model: &ThreeBandEqModel) -> Self { fn new(_sample_rate: f32, _model: &ThreeBandEqModel) -> Self {
Self // Default cause we want to start with 0s in everything
Self::default()
} }
#[inline] #[inline]
@ -47,9 +139,20 @@ impl Plugin for ThreeBandEq {
let input = &ctx.inputs[0].buffers; let input = &ctx.inputs[0].buffers;
let output = &mut ctx.outputs[0].buffers; let output = &mut ctx.outputs[0].buffers;
let sr = ctx.sample_rate;
for i in 0..ctx.nframes { for i in 0..ctx.nframes {
output[0][i] = input[0][i] * model.gain[i]; // frequencies
output[1][i] = input[1][i] * model.gain[i]; let lf = model.low_band[i];
let hf = model.high_band[i];
// gains
let lg = model.low_gain[i];
let mg = model.mid_gain[i];
let hg = model.high_gain[i];
output[0][i] = self.l_eq.process(input[0][i], lf, hf, lg, mg, hg, sr);
output[1][i] = self.r_eq.process(input[1][i], lf, hf, lg, mg, hg, sr);
} }
} }
} }