#![allow(incomplete_features)] #![feature(generic_associated_types)] // morphing algorithm from https://ccrma.stanford.edu/~jhsu/421b/ use baseplug::{Plugin, ProcessContext}; use pvoc::{PhaseBin, PhaseVocoder}; use serde::{Deserialize, Serialize}; use utils::logs::*; baseplug::model! { #[derive(Debug, Serialize, Deserialize)] struct OpiateModel { #[model(min = 0.0, max = 1.0)] #[parameter(name = "morph")] morph: f32, } } impl Default for OpiateModel { fn default() -> Self { Self { morph: 0.0 } } } struct Opiate { pvoc: PhaseVocoder, out_0: Vec, out_1: Vec, out_2: Vec, out_3: Vec, } impl Plugin for Opiate { const NAME: &'static str = "opiate"; const PRODUCT: &'static str = "opiate"; const VENDOR: &'static str = "unnieversal"; const INPUT_CHANNELS: usize = 4; const OUTPUT_CHANNELS: usize = 2; type Model = OpiateModel; #[inline] fn new(sample_rate: f32, _model: &OpiateModel) -> Self { setup_logging("opiate.log"); Self { pvoc: PhaseVocoder::new(4, sample_rate as f64, 64, 4), out_0: vec![0.0; 300], out_1: vec![0.0; 300], out_2: vec![0.0; 300], out_3: vec![0.0; 300], } } #[inline] fn process(&mut self, model: &OpiateModelProcess, ctx: &mut ProcessContext) { let input = &ctx.inputs[0].buffers; let output = &mut ctx.outputs[0].buffers; if input.len() != 4 { for i in 0..ctx.nframes { output[0][i] = 0.0; output[1][i] = 0.0; } return; } let out = &mut [ &mut self.out_0[0..ctx.nframes], &mut self.out_1[0..ctx.nframes], &mut self.out_2[0..ctx.nframes], &mut self.out_3[0..ctx.nframes], ][..]; let morph = model.morph[0] as f64; let imorph = 1.0 - morph; self.pvoc.process( input, out, |_channels: usize, bins: usize, input: &[Vec], output: &mut [Vec]| { for j in 0..bins { // left let mags = morph * (1.0 - input[0][j].amp) + input[0][j].amp; let mags2 = imorph * (1.0 - input[2][j].amp) + input[2][j].amp; let phases = input[0][j].phase - (input[0][j].phase * morph); let phases2 = input[2][j].phase - (input[2][j].phase * imorph); output[0][j].amp = mags * mags2; output[0][j].phase = phases + phases2; // right let mags = morph * (1.0 - input[1][j].amp) + input[1][j].amp; let mags2 = imorph * (1.0 - input[3][j].amp) + input[3][j].amp; let phases = input[1][j].phase - (input[1][j].phase * morph); let phases2 = input[3][j].phase - (input[3][j].phase * imorph); output[1][j].amp = mags * mags2; output[1][j].phase = phases + phases2; } }, ); for i in 0..ctx.nframes { output[0][i] = self.out_0[i]; output[1][i] = self.out_1[i]; self.out_0[i] = 0.0; self.out_1[i] = 0.0; } } } baseplug::vst2!(Opiate, b"opiu");