Skip to content

Instantly share code, notes, and snippets.

@crsaracco
Last active December 4, 2017 20:41
Show Gist options
  • Save crsaracco/7e01e94ec4ef53300ea0afdd50437701 to your computer and use it in GitHub Desktop.
Save crsaracco/7e01e94ec4ef53300ea0afdd50437701 to your computer and use it in GitHub Desktop.
rust-vst segfault
// NOTE: This is the main.rs for the vst PLUGIN
#[macro_use] extern crate vst2;
use vst2::plugin::{Plugin, Info, Category};
use vst2::buffer::AudioBuffer;
struct HighFrequencyToneControl {
parameter: f32,
last_sample_left: f32,
last_sample_right: f32,
}
impl Default for HighFrequencyToneControl {
fn default() -> HighFrequencyToneControl {
HighFrequencyToneControl {
parameter: 0.0,
last_sample_left: 0.0,
last_sample_right: 0.0,
}
}
}
impl Plugin for HighFrequencyToneControl {
fn get_info(&self) -> Info {
Info {
name: "HighFrequencyToneControl".to_string(),
vendor: "crsaracco".to_string(),
// make sure this is different than all of the other VSTs in your host!
unique_id: 1234500003,
parameters: 1,
inputs: 2,
outputs: 2,
category: Category::Effect,
// fill in the rest with the default values
..Info::default()
}
}
fn process(&mut self, buffer: &mut AudioBuffer<f32>) {
// Split out the input and output buffers into two vectors
let (inputs, outputs) = buffer.split();
// For each channel (left/right), "zip" the inputs and outputs together so that it's easier to work with:
let mut channel_num = 0;
for (input_buffer, output_buffer) in inputs.into_iter().zip(outputs) {
// input_buffer and output_buffer refer to our current channel. 0 is left and 1 is right.
for x in 0..input_buffer.len() {
// Calculate the High Frequency Tone Control output:
let last_sample = match channel_num {
0 => self.last_sample_left,
1 => self.last_sample_right,
_ => 0.0,
};
let scaled_parameter = 0.50;
output_buffer[x] = last_sample * scaled_parameter + input_buffer[x] * scaled_parameter;
// Store the current sample as this channels "last output" for next sample:
match channel_num {
0 => self.last_sample_left = input_buffer[x],
1 => self.last_sample_right = input_buffer[x],
_ => (),
};
}
channel_num += 1
}
}
fn get_parameter(&self, index: i32) -> f32 {
match index {
0 => self.parameter,
_ => 0.0,
}
}
fn set_parameter(&mut self, index: i32, value: f32) {
match index {
// We don't want to divide by zero, so we'll clamp the value
0 => self.parameter = value.max(0.01),
_ => (),
}
}
fn get_parameter_name(&self, index: i32) -> String {
match index {
0 => "Parameter".to_string(),
_ => "".to_string(),
}
}
fn get_parameter_text(&self, index: i32) -> String {
match index {
// Convert to a percentage
0 => format!("{}", self.parameter * 0.50),
_ => "".to_string(),
}
}
fn get_parameter_label(&self, index: i32) -> String {
match index {
0 => "%".to_string(),
_ => "".to_string(),
}
}
}
plugin_main!(HighFrequencyToneControl);
// NOTE: This is the main.rs for the vst HOST
extern crate vst2;
use std::sync::{Arc, Mutex};
use std::path::Path;
use std::error::Error;
use vst2::host::{Host, PluginLoader};
use vst2::plugin::Plugin;
use vst2::buffer::AudioBuffer;
#[allow(dead_code)]
struct SampleHost;
impl Host for SampleHost {
fn automate(&mut self, index: i32, value: f32) {
println!("Parameter {} had its value changed to {}", index, value);
}
}
fn main() {
// This is an example of a plugin being loaded. Change this to the appropriate path.
let path = Path::new(
"/home/crs/programming/rust/VSTs/high-frequency-tone-control/target/debug/libhigh_frequency_tone_control.so",
);
// Create the host
let host = Arc::new(Mutex::new(SampleHost));
println!("Loading {}...", path.to_str().unwrap());
// Load the plugin
let mut loader = PluginLoader::load(path, Arc::clone(&host)).unwrap_or_else(
|e| {
panic!("Failed to load plugin: {}", e.description())
},
);
// Create an instance of the plugin
let mut instance = loader.instance().unwrap();
// Get the plugin information
let info = instance.get_info();
println!(
"Loaded '{}':\n\t\
Vendor: {}\n\t\
Presets: {}\n\t\
Parameters: {}\n\t\
VST ID: {}\n\t\
Version: {}\n\t\
Initial Delay: {} samples",
info.name,
info.vendor,
info.presets,
info.parameters,
info.unique_id,
info.version,
info.initial_delay
);
// Initialize the instance
instance.init();
println!("Initialized instance!");
println!("Parameter can be automated: {}", instance.can_be_automated(0));
// Create a new AudioBuffer for the VST instance to process on
// NOTE: This is probably inefficient and probably isn't the right way to do this, but it's what created the segfault:
let mut test_input: Vec<*const f32> = Vec::new();
for _ in 0..4096 {
test_input.push(&0.0);
}
let mut test_output: Vec<*mut f32> = Vec::new();
for _ in 0..4096 {
test_output.push(&mut 0.0);
}
let mut audio_buffer = AudioBuffer::new(
&test_input, &mut test_output, 4096
);
instance.process(&mut audio_buffer);
println!("Closing instance...");
// Close the instance. This is not necessary as the instance is shut down when
// it is dropped as it goes out of scope.
// drop(instance);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment