feat: add resonance compressor and Windows CI
This commit is contained in:
1 parent
3281535a04
commit
3c5b05fdec
31 files changed
+6340
-57
No files matched your search
@@ -0,0 +1,188 @@
|
||||
use nih_plug::prelude::*;
|
||||
use nih_plug_egui::EguiState;
|
||||
use resonance_core::{Focus, Settings};
|
||||
use std::sync::Arc;
|
||||
#[derive(Params)]
|
||||
pub struct FocusParams {
|
||||
#[id = "enabled"]
|
||||
pub enabled: FloatParam,
|
||||
#[id = "frequency"]
|
||||
pub frequency: FloatParam,
|
||||
#[id = "width"]
|
||||
pub width: FloatParam,
|
||||
#[id = "sensitivity"]
|
||||
pub sensitivity: FloatParam,
|
||||
}
|
||||
fn linear(name: &str, v: f32, min: f32, max: f32, unit: &'static str) -> FloatParam {
|
||||
FloatParam::new(name, v, FloatRange::Linear { min, max }).with_unit(unit)
|
||||
}
|
||||
fn log(name: &str, v: f32, min: f32, max: f32, unit: &'static str) -> FloatParam {
|
||||
FloatParam::new(
|
||||
name,
|
||||
v,
|
||||
FloatRange::Skewed {
|
||||
min,
|
||||
max,
|
||||
factor: FloatRange::skew_factor(-2.),
|
||||
},
|
||||
)
|
||||
.with_unit(unit)
|
||||
}
|
||||
impl Default for FocusParams {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: linear("Enabled", 0., 0., 1., "").with_step_size(1.),
|
||||
frequency: log("Frequency", 2000., 20., 20000., " Hz"),
|
||||
width: linear("Width", 0.5, 0.05, 2., " oct"),
|
||||
sensitivity: linear("Sensitivity", 0., -18., 18., " dB"),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Params)]
|
||||
pub struct ResonanceParams {
|
||||
#[persist = "editor"]
|
||||
pub editor: Arc<EguiState>,
|
||||
#[id = "amount"]
|
||||
pub amount: FloatParam,
|
||||
#[id = "sensitivity"]
|
||||
pub sensitivity: FloatParam,
|
||||
#[id = "max-cut"]
|
||||
pub max_cut: FloatParam,
|
||||
#[id = "neighborhood"]
|
||||
pub neighborhood: FloatParam,
|
||||
#[id = "cut-width"]
|
||||
pub cut_width: FloatParam,
|
||||
#[id = "knee"]
|
||||
pub knee: FloatParam,
|
||||
#[id = "attack"]
|
||||
pub attack: FloatParam,
|
||||
#[id = "release"]
|
||||
pub release: FloatParam,
|
||||
#[id = "transient-guard"]
|
||||
pub transient_guard: FloatParam,
|
||||
#[id = "low"]
|
||||
pub low: FloatParam,
|
||||
#[id = "high"]
|
||||
pub high: FloatParam,
|
||||
#[id = "mix"]
|
||||
pub mix: FloatParam,
|
||||
#[id = "output"]
|
||||
pub output: FloatParam,
|
||||
#[id = "bypass"]
|
||||
pub bypass: BoolParam,
|
||||
#[nested(array, group = "Focus")]
|
||||
pub focus: [FocusParams; 4],
|
||||
}
|
||||
impl Default for ResonanceParams {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
editor: EguiState::from_size(1180, 760),
|
||||
amount: linear("Amount", 35., 0., 100., " %"),
|
||||
sensitivity: linear("Sensitivity", 6., 0., 24., " dB"),
|
||||
max_cut: linear("Max cut", 3., 0., 18., " dB"),
|
||||
neighborhood: linear("Neighborhood", 1., 0.25, 2., " oct"),
|
||||
cut_width: linear("Cut width", 0.08, 0.03, 0.5, " oct"),
|
||||
knee: linear("Knee", 3., 0., 12., " dB"),
|
||||
attack: log("Attack", 15., 1., 200., " ms"),
|
||||
release: log("Release", 120., 10., 1000., " ms"),
|
||||
transient_guard: linear("Transient guard", 50., 0., 100., " %"),
|
||||
low: log("Low frequency", 120., 20., 19999., " Hz"),
|
||||
high: log("High frequency", 12000., 21., 20000., " Hz"),
|
||||
mix: linear("Mix", 100., 0., 100., " %"),
|
||||
output: linear("Output", 0., -12., 12., " dB"),
|
||||
bypass: BoolParam::new("Bypass", false).make_bypass(),
|
||||
focus: std::array::from_fn(|_| FocusParams::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ResonanceParams {
|
||||
pub fn floats(&self) -> [&FloatParam; 29] {
|
||||
[
|
||||
&self.amount,
|
||||
&self.sensitivity,
|
||||
&self.max_cut,
|
||||
&self.neighborhood,
|
||||
&self.cut_width,
|
||||
&self.knee,
|
||||
&self.attack,
|
||||
&self.release,
|
||||
&self.transient_guard,
|
||||
&self.low,
|
||||
&self.high,
|
||||
&self.mix,
|
||||
&self.output,
|
||||
&self.focus[0].enabled,
|
||||
&self.focus[0].frequency,
|
||||
&self.focus[0].width,
|
||||
&self.focus[0].sensitivity,
|
||||
&self.focus[1].enabled,
|
||||
&self.focus[1].frequency,
|
||||
&self.focus[1].width,
|
||||
&self.focus[1].sensitivity,
|
||||
&self.focus[2].enabled,
|
||||
&self.focus[2].frequency,
|
||||
&self.focus[2].width,
|
||||
&self.focus[2].sensitivity,
|
||||
&self.focus[3].enabled,
|
||||
&self.focus[3].frequency,
|
||||
&self.focus[3].width,
|
||||
&self.focus[3].sensitivity,
|
||||
]
|
||||
}
|
||||
pub fn settings(&self) -> Settings {
|
||||
let mut s = Settings {
|
||||
amount: self.amount.value(),
|
||||
sensitivity: self.sensitivity.value(),
|
||||
max_cut: self.max_cut.value(),
|
||||
neighborhood: self.neighborhood.value(),
|
||||
cut_width: self.cut_width.value(),
|
||||
knee: self.knee.value(),
|
||||
attack: self.attack.value(),
|
||||
release: self.release.value(),
|
||||
transient_guard: self.transient_guard.value(),
|
||||
low: self.low.value(),
|
||||
high: self.high.value(),
|
||||
mix: self.mix.value(),
|
||||
output: self.output.value(),
|
||||
bypass: self.bypass.value(),
|
||||
focus: std::array::from_fn(|i| Focus {
|
||||
enabled: self.focus[i].enabled.value() >= 0.5,
|
||||
frequency: self.focus[i].frequency.value(),
|
||||
width: self.focus[i].width.value(),
|
||||
sensitivity: self.focus[i].sensitivity.value(),
|
||||
}),
|
||||
};
|
||||
// Independent automation of bounds may cross them; preserve a valid effective range.
|
||||
if s.low >= s.high {
|
||||
s.low = (s.high - 1.).max(20.);
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
pub fn values(s: &Settings) -> [f32; 29] {
|
||||
let mut v = [0.; 29];
|
||||
v[..13].copy_from_slice(&[
|
||||
s.amount,
|
||||
s.sensitivity,
|
||||
s.max_cut,
|
||||
s.neighborhood,
|
||||
s.cut_width,
|
||||
s.knee,
|
||||
s.attack,
|
||||
s.release,
|
||||
s.transient_guard,
|
||||
s.low,
|
||||
s.high,
|
||||
s.mix,
|
||||
s.output,
|
||||
]);
|
||||
for i in 0..4 {
|
||||
v[13 + i * 4..17 + i * 4].copy_from_slice(&[
|
||||
f32::from(s.focus[i].enabled),
|
||||
s.focus[i].frequency,
|
||||
s.focus[i].width,
|
||||
s.focus[i].sensitivity,
|
||||
]);
|
||||
}
|
||||
v
|
||||
}
|
||||
Reference in new issue
Block a user