#![allow(incomplete_features)] #![feature(generic_associated_types)] use baseplug::{Plugin, ProcessContext}; use serde::{Deserialize, Serialize}; baseplug::model! { #[derive(Debug, Serialize, Deserialize)] struct TrituModel { #[model(min = 1.0, max = 100.0)] #[parameter(name = "pregain")] pregain: f32, #[model(min = 0.0, max = 20.0)] #[parameter(name = "drive")] drive: f32, #[model(min = 0.0, max = 3.0)] #[parameter(name = "distortion")] distortion: f32, } } impl Default for TrituModel { fn default() -> Self { Self { pregain: 1.0, drive: 1.0, distortion: 0.0, } } } struct Tritu; impl Plugin for Tritu { const NAME: &'static str = "tritu"; const PRODUCT: &'static str = "tritu"; const VENDOR: &'static str = "unnieversal"; const INPUT_CHANNELS: usize = 2; const OUTPUT_CHANNELS: usize = 2; type Model = TrituModel; #[inline] fn new(_sample_rate: f32, _model: &TrituModel) -> Self { Self } #[inline] fn process(&mut self, model: &TrituModelProcess, ctx: &mut ProcessContext) { let input = &ctx.inputs[0].buffers; let output = &mut ctx.outputs[0].buffers; for i in 0..ctx.nframes { let pregain = model.pregain[i]; let drive = model.drive[i]; let distortion = model.distortion[i]; output[0][i] = trituradora(input[0][i], pregain, drive, distortion); output[1][i] = trituradora(input[1][i], pregain, drive, distortion); } } } fn trituradora(input: f32, pregain: f32, drive: f32, distortion: f32) -> f32 { // multiply by pregain and hard clip let hard = (input * pregain).clamp(-1.0, 1.0); // multiply by drive let val = hard * drive; // weird thingy i made up: https://www.desmos.com/calculator/bzprjqhudd val.tanh() * (distortion / val).cos() } baseplug::vst2!(Tritu, b"tri2");