#![allow(incomplete_features)] #![feature(generic_associated_types)] use baseplug::{Plugin, ProcessContext}; use serde::{Deserialize, Serialize}; baseplug::model! { #[derive(Debug, Serialize, Deserialize)] struct BistortionModel { #[model(min = 0.0, max = 10.0)] #[parameter(name = "a")] a: f32, #[model(min = 0.0, max = 30.0)] #[parameter(name = "b")] b: f32, } } impl Default for BistortionModel { fn default() -> Self { Self { a: 1.0, b: 1.0 } } } struct Bistortion { frame: usize, } impl Plugin for Bistortion { const NAME: &'static str = "bistortion"; const PRODUCT: &'static str = "bistortion"; const VENDOR: &'static str = "unnieversal"; const INPUT_CHANNELS: usize = 2; const OUTPUT_CHANNELS: usize = 2; type Model = BistortionModel; #[inline] fn new(_sample_rate: f32, _model: &BistortionModel) -> Self { Self { frame: 0 } } #[inline] fn process(&mut self, model: &BistortionModelProcess, ctx: &mut ProcessContext) { let input = &ctx.inputs[0].buffers; let output = &mut ctx.outputs[0].buffers; for i in 0..ctx.nframes { let a = model.a[i]; let b = model.b[i]; let p = self.frame as f32 / ctx.sample_rate; output[0][i] = process(input[0][i], p, a, b); output[1][i] = process(input[1][i], p, a, b); self.frame += 1; } } } // https://www.desmos.com/calculator/8gmb283p0v fn process(v: f32, p: f32, a: f32, b: f32) -> f32 { (v * a * (b * v).cos()).tanh() } baseplug::vst2!(Bistortion, b"bist");