#![allow(incomplete_features)] #![feature(generic_associated_types)] use baseplug::{Plugin, ProcessContext}; use serde::{Deserialize, Serialize}; use utils::threeband::*; baseplug::model! { #[derive(Debug, Serialize, Deserialize)] struct ThreeBandWidthModel { #[model(min = 0.0, max = 15000.0)] #[parameter(name = "low band")] low_band: f32, #[model(min = 0.0, max = 15000.0)] #[parameter(name = "mid band")] high_band: f32, #[model(min = 0.0, max = 3.0)] #[parameter(name = "low width")] low_width: f32, #[model(min = 0.0, max = 3.0)] #[parameter(name = "mid width")] mid_width: f32, #[model(min = 0.0, max = 3.0)] #[parameter(name = "high width")] high_width: f32, } } impl Default for ThreeBandWidthModel { fn default() -> Self { Self { low_band: 800.0, high_band: 5000.0, low_width: 1.0, mid_width: 1.0, high_width: 1.0, } } } #[derive(Default)] struct ThreeBandWidth { l: ThreeBandSplitter, r: ThreeBandSplitter, } impl Plugin for ThreeBandWidth { const NAME: &'static str = "threebandwidth"; const PRODUCT: &'static str = "threebandwidth"; const VENDOR: &'static str = "unnieversal"; const INPUT_CHANNELS: usize = 2; const OUTPUT_CHANNELS: usize = 2; type Model = ThreeBandWidthModel; #[inline] fn new(_sample_rate: f32, _model: &ThreeBandWidthModel) -> Self { // Default cause we want to start with 0s in everything Self::default() } #[inline] fn process(&mut self, model: &ThreeBandWidthModelProcess, ctx: &mut ProcessContext) { let input = &ctx.inputs[0].buffers; let output = &mut ctx.outputs[0].buffers; let sr = ctx.sample_rate; for i in 0..ctx.nframes { // frequencies let lf = model.low_band[i]; let hf = model.high_band[i]; // split into bands let (low_l, mid_l, high_l) = self.l.process(input[0][i], lf, hf, sr); let (low_r, mid_r, high_r) = self.r.process(input[1][i], lf, hf, sr); // widen each band let (low_l, low_r) = wide(model.low_width[i], low_l, low_r); let (mid_l, mid_r) = wide(model.mid_width[i], mid_l, mid_r); let (high_l, high_r) = wide(model.high_width[i], high_l, high_r); output[0][i] = low_l + mid_l + high_l; output[1][i] = low_r + mid_r + high_r; } } } // From https://www.musicdsp.org/en/latest/Effects/256-stereo-width-control-obtained-via-transfromation-matrix.html fn wide(width: f32, l: f32, r: f32) -> (f32, f32) { let tmp = 1.0 / f32::max(1.0 + width, 2.0); let coef_m = tmp; let coef_s = width * tmp; let m = (l + r) * coef_m; let s = (r - l) * coef_s; (m - s, m + s) } baseplug::vst2!(ThreeBandWidth, b"3bsw");