Skip to content

Commit

Permalink
Merge pull request #8 from SolarLiner/feat/parameters
Browse files Browse the repository at this point in the history
Parameters as shared values
  • Loading branch information
SolarLiner authored Feb 12, 2024
2 parents 9c2edd3 + ad88ae2 commit 79173a3
Show file tree
Hide file tree
Showing 10 changed files with 499 additions and 138 deletions.
30 changes: 30 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,19 @@ repository = "https://github.com/SolarLiner/valib"
keywords = ["virtual-analog", "audio", "plugin", "va-modeling", "dsp"]

[workspace.dependencies]
enum-map = "2.7.3"
nih_plug = { git = "https://github.com/geom3trik/nih-plug.git", branch = "vizia-update" }
nih_plug_vizia = { git = "https://github.com/geom3trik/nih-plug.git", branch = "vizia-update" }
nalgebra = "0.32.3"


[dependencies]
az = "1.2.1"
enum-map.workspace = true
nalgebra.workspace = true
num-traits = "0.2.17"
numeric_literals = "0.2.0"
portable-atomic = { version = "1.6.0", features = ["float"] }
simba = { version = "0.8.1", features = ["wide"] }

[dev-dependencies]
Expand Down
4 changes: 3 additions & 1 deletion examples/svfmixer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ keywords.workspace = true
crate-type = ["cdylib"]

[dependencies]
nih_plug = { workspace = true }
enum-map.workspace = true
nalgebra.workspace = true
nih_plug.workspace = true
valib = { path = "../.." }
129 changes: 129 additions & 0 deletions examples/svfmixer/src/dsp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
use enum_map::{enum_map, Enum, EnumMap};
use nalgebra::SMatrix;
use nih_plug::util::db_to_gain_fast;
use valib::dsp::blocks::ModMatrix;
use valib::dsp::parameter::{HasParameters, Parameter, SmoothedParam};
use valib::dsp::DSP;
use valib::filters::svf::Svf;
use valib::oversample::Oversampled;
use valib::saturators::{Clipper, Saturator, Slew};
use valib::simd::{AutoSimd, SimdValue};
use valib::Scalar;

type Sample = AutoSimd<[f32; 2]>;

pub type Dsp = Oversampled<Sample, DspInner>;

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Enum)]
pub enum DspParam {
Drive,
Cutoff,
Resonance,
LpGain,
BpGain,
HpGain,
}

type Filter = Svf<Sample, OpAmp<Sample>>;

pub struct DspInner {
params: EnumMap<DspParam, SmoothedParam>,
filter: Filter,
mod_matrix: ModMatrix<Sample, 3, 1>,
}

impl DspInner {
pub(crate) fn set_samplerate(&mut self, samplerate: f32) {
for (_, param) in self.params.iter_mut() {
param.set_samplerate(samplerate);
}
self.filter.set_samplerate(samplerate);
}
}

impl DspInner {
pub fn new(samplerate: f32) -> Self {
let params = enum_map! {
DspParam::Drive => Parameter::new(1.0).named("Drive").smoothed_linear(samplerate, 10.0),
DspParam::Cutoff => Parameter::new(3000.0).named("Cutoff").smoothed_linear(samplerate, 1e-6),
DspParam::Resonance => Parameter::new(0.5).named("Resonance").smoothed_linear(samplerate, 10.0),
DspParam::LpGain => Parameter::new(1.0).named("LP Gain").smoothed_linear(samplerate, 10.0),
DspParam::BpGain => Parameter::new(0.0).named("BP Gain").smoothed_linear(samplerate, 10.0),
DspParam::HpGain => Parameter::new(0.0).named("HP Gain").smoothed_linear(samplerate, 10.0),
};
let filter = Filter::new(
Sample::splat(samplerate),
Sample::splat(3000.0),
Sample::splat(0.5),
);
let mod_matrix = ModMatrix {
weights: SMatrix::<_, 1, 3>::new(
Sample::splat(1.0),
Sample::splat(0.0),
Sample::splat(0.0),
),
..ModMatrix::default()
};
Self {
params,
filter,
mod_matrix,
}
}
}

impl HasParameters for DspInner {
type Enum = DspParam;

fn get_parameter(&self, param: Self::Enum) -> &Parameter {
&self.params[param].param
}
}

impl DSP<1, 1> for DspInner {
type Sample = Sample;

fn process(&mut self, [x]: [Self::Sample; 1]) -> [Self::Sample; 1] {
self.filter
.set_cutoff(Sample::splat(self.params[DspParam::Cutoff].next_sample()));
self.filter.set_r(Sample::splat(
1.0 - self.params[DspParam::Resonance].next_sample(),
));
self.mod_matrix.weights.x = Sample::splat(self.params[DspParam::LpGain].next_sample());
self.mod_matrix.weights.y = Sample::splat(self.params[DspParam::BpGain].next_sample());
self.mod_matrix.weights.z = Sample::splat(self.params[DspParam::HpGain].next_sample());

let drive = Sample::splat(db_to_gain_fast(self.params[DspParam::Drive].next_sample()));
let [out] = self.mod_matrix.process(self.filter.process([x * drive]));
[out / drive]
}
}

#[derive(Debug, Clone, Copy)]
struct OpAmp<T>(Clipper, Slew<T>);

impl<T: Scalar> Default for OpAmp<T> {
fn default() -> Self {
Self(Default::default(), Default::default())
}
}

impl<T: Scalar> Saturator<T> for OpAmp<T>
where
Clipper: Saturator<T>,
Slew<T>: Saturator<T>,
{
fn saturate(&self, x: T) -> T {
self.1.saturate(self.0.saturate(x))
}

fn sat_diff(&self, x: T) -> T {
self.0.sat_diff(x) * self.1.sat_diff(self.0.saturate(x))
}

fn update_state(&mut self, x: T, y: T) {
let xc = self.0.saturate(x);
self.0.update_state(x, xc);
self.1.update_state(xc, y);
}
}
Loading

0 comments on commit 79173a3

Please sign in to comment.