Last active
December 4, 2017 20:41
-
-
Save crsaracco/7e01e94ec4ef53300ea0afdd50437701 to your computer and use it in GitHub Desktop.
rust-vst segfault
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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