unnieversal/crates/hysteria/src/lib.rs

93 lines
2.4 KiB
Rust

#![allow(incomplete_features)]
#![feature(generic_associated_types)]
use baseplug::{Plugin, ProcessContext};
use serde::{Deserialize, Serialize};
mod hysteresis;
use hysteresis::*;
baseplug::model! {
#[derive(Debug, Serialize, Deserialize)]
struct HysteriaModel {
#[model(min = 0.0, max = 10.0)]
#[parameter(name = "drive")]
drive: f32,
#[model(min = 0.0, max = 1.0)]
#[parameter(name = "saturation")]
sat: f32,
#[model(min = 0.0, max = 1.0)]
#[parameter(name = "width")]
width: f32,
}
}
impl Default for HysteriaModel {
fn default() -> Self {
Self {
drive: 1.,
sat: 0.5,
width: 0.5,
}
}
}
struct Hysteria {
hysteresis_l: Hysteresis,
hysteresis_r: Hysteresis,
}
impl Plugin for Hysteria {
const NAME: &'static str = "hysteria";
const PRODUCT: &'static str = "hysteria";
const VENDOR: &'static str = "unnieversal";
const INPUT_CHANNELS: usize = 2;
const OUTPUT_CHANNELS: usize = 2;
type Model = HysteriaModel;
#[inline]
fn new(_sample_rate: f32, _model: &HysteriaModel) -> Self {
Self {
hysteresis_l: Hysteresis::new(),
hysteresis_r: Hysteresis::new(),
}
}
#[inline]
fn process(&mut self, model: &HysteriaModelProcess, ctx: &mut ProcessContext<Self>) {
let input = &ctx.inputs[0].buffers;
let output = &mut ctx.outputs[0].buffers;
// Update sample rate
let sample_rate = ctx.sample_rate;
self.hysteresis_l.set_sample_rate(sample_rate);
self.hysteresis_r.set_sample_rate(sample_rate);
for i in 0..ctx.nframes {
// Makeup is an added extra to make it work similarly with all params
let makeup = calc_makeup(model.width[i], model.sat[i]);
output[0][i] = self.hysteresis_l.process(
model.drive[i],
model.width[i],
model.sat[i],
input[0][i],
) * makeup;
output[1][i] = self.hysteresis_r.process(
model.drive[i],
model.width[i],
model.sat[i],
input[1][i],
) * makeup;
}
}
}
fn calc_makeup(width: f32, sat: f32) -> f32 {
(1.0 + 0.6 * width) / (0.5 + 1.5 * (1.0 - sat))
}
baseplug::vst2!(Hysteria, b"hyst");