Commit 5f5496b5 authored by Aske Simon Christensen's avatar Aske Simon Christensen
Browse files

Ported to thread-safe rust-vst branch

parent 2b7b702f
......@@ -5,7 +5,7 @@ authors = ["Aske Simon Christensen <blueberry@loonies.dk>"]
build = "build.rs"
[dependencies]
vst = { git = "https://github.com/rust-dsp/rust-vst" }
vst = { git = "https://github.com/askeksa/rust-vst", branch = "thread_safe_plugin" }
rand = "0.3"
[build-dependencies]
......
......@@ -63,7 +63,7 @@ pub trait SoundParameters {
}
pub trait SoundGenerator {
type Parameters: PartialEq + SoundParameters + Clone;
type Parameters: SoundParameters + PartialEq + Clone + Send + Sync;
type Output: Default + Copy + Into<Sample>;
type Global: Default;
......
use std::collections::{HashMap, VecDeque};
use std::marker::PhantomData;
use std::sync::RwLock;
use std::ops::Deref;
use std::sync::{Arc, RwLock};
use vst::api::{Events, Supported};
use vst::buffer::AudioBuffer;
use vst::event::{Event, MidiEvent};
use vst::host::Host;
use vst::plugin::{CanDo, Category, HostCallback, Info, Plugin};
use vst::plugin::{CanDo, Category, HostCallback, Info, Plugin, PluginParameters};
use cache::SoundCache;
use generate::{Sample, SoundGenerator, SoundParameters};
......@@ -118,7 +119,7 @@ pub trait SynthInfo {
fn get_info() -> Info;
}
pub struct SynthPlugin<G: SoundGenerator, S: SynthInfo> {
pub struct SynthPlugin<G: SoundGenerator + 'static, S: SynthInfo> {
sample_rate: f32,
time: usize,
notes: Vec<Note>,
......@@ -126,11 +127,10 @@ pub struct SynthPlugin<G: SoundGenerator, S: SynthInfo> {
cache: Vec<SoundCache<G>>,
cached_sound_params: G::Parameters,
params: RwLock<SynthPluginParameters<G>>,
global: G::Global,
params: Arc<RwLockWrapper<SynthPluginParameters<G>>>,
phantom: PhantomData<S>
}
......@@ -139,6 +139,20 @@ struct SynthPluginParameters<G: SoundGenerator> {
values: Vec<f32>,
map: HashMap<&'static str, f32>,
sound_params: G::Parameters,
sample_rate: f32,
}
// Work around orphan rule
struct RwLockWrapper<T> {
inner: RwLock<T>
}
impl<T> Deref for RwLockWrapper<T> {
type Target = RwLock<T>;
fn deref(&self) -> &RwLock<T> {
&self.inner
}
}
fn make_param_map(param_names: &[&'static str], param_values: &[f32]) -> HashMap<&'static str, f32> {
......@@ -164,7 +178,8 @@ impl<G: SoundGenerator, S: SynthInfo> Default for SynthPlugin<G, S> {
host: None,
values: param_values,
map: param_map,
sound_params: sound_params.clone()
sound_params: sound_params.clone(),
sample_rate: sample_rate,
};
SynthPlugin {
......@@ -175,7 +190,7 @@ impl<G: SoundGenerator, S: SynthInfo> Default for SynthPlugin<G, S> {
cache: cache,
cached_sound_params: sound_params,
params: RwLock::new(params),
params: Arc::new(RwLockWrapper { inner: RwLock::new(params) }),
global: G::Global::default(),
......@@ -227,15 +242,7 @@ impl<G: SoundGenerator, S: SynthInfo> Plugin for SynthPlugin<G, S> {
}
fn process(&mut self, buffer: &mut AudioBuffer<f32>) {
{
let params: &SynthPluginParameters<G> = &self.params.read().unwrap();
if params.sound_params != self.cached_sound_params {
self.cached_sound_params = params.sound_params.clone();
for c in &mut self.cache {
c.invalidate();
}
}
}
self.update_cache();
let mut outputs = buffer.split().1;
for i in 0..outputs[0].len() {
......@@ -252,44 +259,50 @@ impl<G: SoundGenerator, S: SynthInfo> Plugin for SynthPlugin<G, S> {
fn set_sample_rate(&mut self, rate: f32) {
self.sample_rate = rate;
self.build_sound_params();
let params: &mut SynthPluginParameters<G> = &mut self.params.write().unwrap();
params.sample_rate = rate;
params.build_sound_params();
}
fn get_parameter_object(&mut self) -> Arc<PluginParameters> {
Arc::clone(&self.params) as Arc<PluginParameters>
}
}
impl<G: SoundGenerator> PluginParameters for RwLockWrapper<SynthPluginParameters<G>> {
fn get_parameter_name(&self, index: i32) -> String {
G::Parameters::names()[index as usize].to_string()
}
fn get_parameter_text(&self, index: i32) -> String {
let params: &SynthPluginParameters<G> = &self.params.read().unwrap();
let params: &SynthPluginParameters<G> = &self.read().unwrap();
params.sound_params.display(G::Parameters::names()[index as usize], &params.map).0
}
fn get_parameter_label(&self, index: i32) -> String {
let params: &SynthPluginParameters<G> = &self.params.read().unwrap();
let params: &SynthPluginParameters<G> = &self.read().unwrap();
params.sound_params.display(G::Parameters::names()[index as usize], &params.map).1
}
fn get_parameter(&self, index: i32) -> f32 {
let params: &SynthPluginParameters<G> = &self.params.read().unwrap();
let params: &SynthPluginParameters<G> = &self.read().unwrap();
params.values[index as usize]
}
fn set_parameter(&mut self, index: i32, value: f32) {
{
let params: &mut SynthPluginParameters<G> = &mut self.params.write().unwrap();
params.values[index as usize] = value;
fn set_parameter(&self, index: i32, value: f32) {
let params: &mut SynthPluginParameters<G> = &mut self.write().unwrap();
params.values[index as usize] = value;
if let Some(ref mut host) = params.host {
for name in G::Parameters::influence(G::Parameters::names()[index as usize]) {
if let Some(p) = G::Parameters::names().iter().position(|n| *n == name) {
params.values[p] = infinitesimal_change(params.values[p]).min(1.0);
host.automate(p as i32, params.values[p]);
}
if let Some(ref mut host) = params.host {
for name in G::Parameters::influence(G::Parameters::names()[index as usize]) {
if let Some(p) = G::Parameters::names().iter().position(|n| *n == name) {
params.values[p] = infinitesimal_change(params.values[p]).min(1.0);
host.automate(p as i32, params.values[p]);
}
}
}
self.build_sound_params();
params.build_sound_params();
}
}
......@@ -337,10 +350,21 @@ impl<G: SoundGenerator, S: SynthInfo> SynthPlugin<G, S> {
sample
}
fn update_cache(&mut self) {
let params: &SynthPluginParameters<G> = &self.params.read().unwrap();
if params.sound_params != self.cached_sound_params {
self.cached_sound_params = params.sound_params.clone();
for c in &mut self.cache {
c.invalidate();
}
}
}
}
impl<G: SoundGenerator> SynthPluginParameters<G> {
fn build_sound_params(&mut self) {
let params: &mut SynthPluginParameters<G> = &mut self.params.write().unwrap();
params.map = make_param_map(G::Parameters::names(), &params.values);
params.sound_params = G::Parameters::build(&params.map, self.sample_rate);
self.map = make_param_map(G::Parameters::names(), &self.values);
self.sound_params = G::Parameters::build(&self.map, self.sample_rate);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment