Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Command line: opannotate --source
- *
- * Interpretation of command line:
- * Output annotated source file with samples
- * Output all files
- *
- * CPU: AMD64 generic, speed 4100 MHz (estimated)
- * Counted CPU_CLK_UNHALTED events (CPU Clocks not Halted) with a unit mask of 0x00 (No unit mask) count 100000
- */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/slice/mod.rs"
- *
- * 222897 21.8343
- */
- /* <[T] as core::slice::SliceExt>::len total: 2 2.0e-04 */
- /* <[T] as core::slice::SliceExt>::iter_mut total: 1 9.8e-05 */
- /* <[T] as core::slice::SliceExt>::as_mut_ptr total: 1 9.8e-05 */
- /* core::slice::<impl core::ops::index::Index<I> for [T]>::index total: 67038 6.5668 */
- /* core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut total: 32753 3.2084 */
- /* <usize as core::slice::SliceIndex<[T]>>::index total: 32818 3.2147 */
- /* <usize as core::slice::SliceIndex<[T]>>::index_mut total: 17654 1.7293 */
- /* core::slice::size_from_ptr total: 35 0.0034 */
- /* <core::slice::IterMut<'a, T> as core::iter::iterator::Iterator>::next total: 113 0.0111 */
- /* core::slice::from_raw_parts total: 48359 4.7371 */
- /* core::slice::from_raw_parts total: 1 9.8e-05 */
- /* core::slice::from_raw_parts_mut total: 24121 2.3628 */
- /* core::slice::from_raw_parts_mut total: 1 9.8e-05 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/liballoc/vec.rs"
- *
- * 181207 17.7505
- */
- /* <alloc::vec::Vec<T> as core::ops::index::Index<I>>::index total: 63174 6.1883 */
- /* <alloc::vec::Vec<T> as core::ops::index::IndexMut<I>>::index_mut total: 33060 3.2385 */
- /* <alloc::vec::Vec<T> as core::ops::deref::Deref>::deref total: 58420 5.7226 */
- /* <alloc::vec::Vec<T> as core::ops::deref::DerefMut>::deref_mut total: 26553 2.6010 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/ptr.rs"
- *
- * 173299 16.9758
- */
- /* core::ptr::null_mut total: 580 0.0568 */
- /* core::ptr::swap_nonoverlapping total: 5779 0.5661 */
- /* core::ptr::swap_nonoverlapping_bytes total: 15746 1.5424 */
- /* core::ptr::<impl *mut T>::is_null total: 77205 7.5628 */
- /* core::ptr::<impl *mut T>::offset total: 43 0.0042 */
- /* core::ptr::<impl *mut T>::offset total: 54173 5.3066 */
- /* <core::ptr::Unique<T>>::as_ptr total: 19773 1.9369 */
- /*
- * Total samples for file : "/home/cyrus/projects/piano/src/string.rs"
- *
- * 124694 12.2146
- */
- :pub struct String {
- : length: usize,
- : dispersion: f32,
- : loss: f32,
- : termination_points: usize,
- : termination_force: f32,
- : y: Vec<f32>,
- : v: Vec<f32>
- :}
- :
- :pub fn new(length: usize, dispersion: f32, loss: f32, termination_points: usize) -> String {
- : let y: Vec<f32> = vec![0_f32; length];
- : let mut v: Vec<f32> = vec![0_f32; length];
- : v[10] = -10_f32;
- : let termination_force = 1_f32/(termination_points as f32);
- : String {
- : length: length-1,
- : dispersion,
- : loss,
- : termination_points,
- : termination_force,
- : y,
- : v
- : }
- :}
- :
- 3 2.9e-04 :pub fn update(s: &mut String) -> (f32, f32) { /* piano::string::update total: 124694 12.2146 */
- 17893 1.7527 : for i in 0..s.length-1 { // calculate forces
- 25503 2.4982 : let energy = (s.y[i]-s.y[i+1])*s.dispersion;
- 16699 1.6358 : s.v[i+1] = (s.v[i+1] + energy) * s.loss;
- 17379 1.7024 : s.v[i] = s.v[i] - energy;
- : }
- 19212 1.8819 : for i in 0..s.length { // apply forces
- 26570 2.6027 : s.y[i] = s.y[i] + s.v[i]; // might be better to do loss here
- : }
- 375 0.0367 : for i in 0..s.termination_points { // soft terminations
- 512 0.0502 : s.y[(s.length+i-i*2)] = s.y[(s.length+i-i*2)]*(s.termination_force*i as f32);
- 305 0.0299 : s.y[i] = s.y[i]*(s.termination_force*(i as f32));
- : }
- 30 0.0029 : let force_left = s.v[0];
- 35 0.0034 : let force_right = s.v[s.length];
- 20 0.0020 : s.y[0] = 0_f32;
- 49 0.0048 : s.y[s.length] = 0_f32;
- 43 0.0042 : s.v[0] = 0_f32;
- 37 0.0036 : s.v[s.length] = 0_f32;
- 24 0.0024 : (force_left, force_right) // return v forces at termination points
- 5 4.9e-04 :}
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/num/mod.rs"
- *
- * 98838 9.6819
- */
- /* core::num::<impl usize>::checked_add total: 39118 3.8319 */
- /* core::num::<impl usize>::overflowing_add total: 59720 5.8500 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/iter/range.rs"
- *
- * 48902 4.7903
- */
- /* <usize as core::iter::range::Step>::add_usize total: 21476 2.1037 */
- /* core::iter::range::<impl core::iter::iterator::Iterator for core::ops::range::Range<A>>::next total: 15126 1.4817 */
- /* <T as core::iter::range::PrivateTryFromUsize>::private_try_from total: 12300 1.2049 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/liballoc/raw_vec.rs"
- *
- * 40403 3.9577
- */
- /* <alloc::raw_vec::RawVec<T, A>>::ptr total: 40403 3.9577 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/result.rs"
- *
- * 27543 2.6980
- */
- /* <core::result::Result<T, E>>::map_err total: 27543 2.6980 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/convert.rs"
- *
- * 13005 1.2739
- */
- /* <T as core::convert::From<T>>::from total: 2272 0.2226 */
- /* <T as core::convert::TryFrom<U>>::try_from total: 10733 1.0514 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/mem.rs"
- *
- * 8132 0.7966
- */
- /* core::mem::size_of total: 2942 0.2882 */
- /* core::mem::size_of total: 47 0.0046 */
- /* core::mem::size_of total: 1446 0.1416 */
- /* core::mem::align_of total: 1 9.8e-05 */
- /* core::mem::uninitialized total: 1370 0.1342 */
- /* core::mem::swap total: 2326 0.2278 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/cmp.rs"
- *
- * 2880 0.2821
- */
- /* core::cmp::impls::<impl core::cmp::PartialOrd for usize>::lt total: 2880 0.2821 */
- /*
- * Total samples for file : "/home/cyrus/projects/piano/src/lib.rs"
- *
- * 104 0.0102
- */
- :const POINTS: usize = 200;
- :
- :#[macro_use]
- :extern crate vst;
- :use vst::plugin::{Info, Plugin};
- :use vst::buffer::AudioBuffer;
- :use vst::event::Event;
- :use vst::api::Events;
- :mod string;
- :
- :struct Piano {
- : string: string::String,
- :}
- :
- :impl Default for Piano {
- : fn default() -> Piano {
- : Piano {
- : string: string::new(POINTS, 1_f32, 1_f32, 3)
- : }
- : }
- :}
- :
- :impl Plugin for Piano {
- : fn init(&mut self) {
- : //let mut self.string = string::new(500, 1_f32, 1_f32, 3);
- : }
- : fn get_info(&self) -> Info {
- : Info {
- : name: "Piano".to_string(),
- : unique_id: 0,
- : inputs: 0,
- : outputs: 1,
- : ..Default::default()
- : }
- : }
- : fn process_events(&mut self, events: &Events) {
- : for event in events.events() {
- : match event {
- : Event::Midi(ev) => {
- : //midi stuff
- : self.string = string::new(POINTS, 1_f32, 1_f32, 3);
- : }, _ => ()
- : }
- : }
- : }
- 3 2.9e-04 : fn process(&mut self, buffer: &mut AudioBuffer<f32>) { /* <piano::Piano as vst::plugin::Plugin>::process total: 104 0.0102 */
- : let (_, output_buffer) = buffer.split();
- 4 3.9e-04 : for output_channel in output_buffer.into_iter() {
- 74 0.0072 : for output_sample in output_channel {
- 8 7.8e-04 : let (left, right) = string::update(&mut self.string);
- 14 0.0014 : *output_sample = left/10_f32
- : }
- : }
- 1 9.8e-05 : }
- :}
- :
- :plugin_main!(Piano);
- :
- :#[cfg(test)]
- :mod tests {
- : use string;
- : #[test]
- : fn test_string_setup() {
- : let mut string = string::new(100, 1_f32, 1_f32, 3);
- : }
- : #[test]
- : fn test_string_update() {
- : let mut string = string::new(100, 1_f32, 1_f32, 3);
- : string::update(&mut string);
- : }
- :}
- /*
- * Total samples for file : "/build/gcc/src/gcc/libstdc++-v3/libsupc++/new_op.cc"
- *
- * 101 0.0099
- */
- /* operator new(unsigned long) total: 101 0.0099 */
- /*
- * Total samples for file : "/build/rust/src/rustc-1.26.0-src/src/libcore/iter/traits.rs"
- *
- * 64 0.0063
- */
- /* <I as core::iter::traits::IntoIterator>::into_iter total: 64 0.0063 */
- /*
- * Total samples for file : "/build/gcc/src/gcc/libstdc++-v3/libsupc++/del_op.cc"
- *
- * 42 0.0041
- */
- /* operator delete(void*) total: 42 0.0041 */
- /*
- * Total samples for file : "/home/cyrus/.cargo/registry/src/github.com-1ecc6299db9ec823/vst-0.0.1/src/buffer.rs"
- *
- * 11 0.0011
- */
- ://! Buffers to safely work with audio samples.
- :
- :use num_traits::Float;
- :
- :use std::slice;
- :use std::iter::Zip;
- :
- :/// `AudioBuffer` contains references to the audio buffers for all input and output channels
- :pub struct AudioBuffer<'a, T: 'a + Float> {
- : inputs: &'a [*const T],
- : outputs: &'a mut [*mut T],
- : samples: usize,
- :}
- :
- :impl<'a, T: 'a + Float> AudioBuffer<'a, T> {
- : /// Create an `AudioBuffer` from slices of raw pointers. Useful in a Rust VST host.
- : #[inline]
- : pub fn new(inputs: &'a [*const T], outputs: &'a mut [*mut T], samples: usize) -> Self {
- : Self {
- : inputs: inputs,
- : outputs: outputs,
- : samples: samples,
- : }
- : }
- :
- : /// Create an `AudioBuffer` from raw pointers.
- : /// Only really useful for interacting with the VST API.
- : #[inline]
- 1 9.8e-05 : pub unsafe fn from_raw(
- /* <vst::buffer::AudioBuffer<'a, T>>::from_raw total: 1 9.8e-05 */
- : input_count: usize,
- : output_count: usize,
- : inputs_raw: *const *const T,
- : outputs_raw: *mut *mut T,
- : samples: usize,
- : ) -> Self {
- : Self {
- : inputs: slice::from_raw_parts(inputs_raw, input_count),
- : outputs: slice::from_raw_parts_mut(outputs_raw, output_count),
- : samples: samples,
- : }
- : }
- :
- : /// The number of input channels that this buffer was created for
- : #[inline]
- : pub fn input_count(&self) -> usize {
- : self.inputs.len()
- : }
- :
- : /// The number of output channels that this buffer was created for
- : #[inline]
- : pub fn output_count(&self) -> usize {
- : self.outputs.len()
- : }
- :
- : /// The number of samples in this buffer (same for all channels)
- : #[inline]
- : pub fn samples(&self) -> usize {
- : self.samples
- : }
- :
- : /// The raw inputs to pass to processReplacing
- : #[inline]
- : pub(crate) fn raw_inputs(&self) -> &[*const T] {
- : self.inputs
- : }
- :
- : /// The raw outputs to pass to processReplacing
- : #[inline]
- : pub(crate) fn raw_outputs(&mut self) -> &mut [*mut T] {
- : &mut self.outputs
- : }
- :
- : /// Split this buffer into separate inputs and outputs.
- : #[inline]
- 1 9.8e-05 : pub fn split<'b>(&'b mut self) -> (Inputs<'b, T>, Outputs<'b, T>)
- /* <vst::buffer::AudioBuffer<'a, T>>::split total: 3 2.9e-04 */
- : where
- : 'a: 'b,
- : {
- 1 9.8e-05 : (
- : Inputs {
- : bufs: self.inputs,
- : samples: self.samples,
- : },
- : Outputs {
- 1 9.8e-05 : bufs: self.outputs,
- : samples: self.samples,
- : },
- : )
- : }
- :
- : /// Zip together buffers.
- : #[inline]
- : pub fn zip<'b>(&'b mut self) -> Zip<InputIterator<'b, T>, OutputIterator<'b, T>>
- : where
- : 'a: 'b,
- : {
- : let (inputs, outputs) = self.split();
- : inputs.into_iter().zip(outputs)
- : }
- :}
- :
- :use std::ops::{Index, IndexMut};
- :
- :/// Wrapper type to access the buffers for the input channels of an `AudioBuffer` in a safe way.
- :/// Behaves like a slice.
- :#[derive(Copy, Clone)]
- :pub struct Inputs<'a, T: 'a> {
- : bufs: &'a [*const T],
- : samples: usize,
- :}
- :
- :impl<'a, T> Inputs<'a, T> {
- : /// Number of channels
- : pub fn len(&self) -> usize {
- : self.bufs.len()
- : }
- :
- : /// Returns true if the buffer is empty
- : pub fn is_empty(&self) -> bool {
- : self.len() == 0
- : }
- :
- : /// Access channel at the given index, unchecked
- : pub fn get(&self, i: usize) -> &'a [T] {
- : unsafe { slice::from_raw_parts(self.bufs[i], self.samples) }
- : }
- :
- : /// Split borrowing at the given index, like for slices
- : pub fn split_at(&self, i: usize) -> (Inputs<'a, T>, Inputs<'a, T>) {
- : let (l, r) = self.bufs.split_at(i);
- : (
- : Inputs {
- : bufs: l,
- : samples: self.samples,
- : },
- : Inputs {
- : bufs: r,
- : samples: self.samples,
- : },
- : )
- : }
- :}
- :
- :impl<'a, T> Index<usize> for Inputs<'a, T> {
- : type Output = [T];
- :
- : fn index(&self, i: usize) -> &Self::Output {
- : self.get(i)
- : }
- :}
- :
- :/// Iterator over buffers for input channels of an `AudioBuffer`.
- :pub struct InputIterator<'a, T: 'a> {
- : data: Inputs<'a, T>,
- : i: usize,
- :}
- :
- :impl<'a, T> Iterator for InputIterator<'a, T> {
- : type Item = &'a [T];
- :
- : fn next(&mut self) -> Option<Self::Item> {
- : if self.i < self.data.len() {
- : let val = self.data.get(self.i);
- : self.i += 1;
- : Some(val)
- : } else {
- : None
- : }
- : }
- :}
- :
- :impl<'a, T: Sized> IntoIterator for Inputs<'a, T> {
- : type Item = &'a [T];
- : type IntoIter = InputIterator<'a, T>;
- :
- : fn into_iter(self) -> Self::IntoIter {
- : InputIterator { data: self, i: 0 }
- : }
- :}
- :
- :/// Wrapper type to access the buffers for the output channels of an `AudioBuffer` in a safe way.
- :/// Behaves like a slice.
- :#[derive(Copy, Clone)]
- :pub struct Outputs<'a, T: 'a> {
- : bufs: &'a [*mut T],
- : samples: usize,
- :}
- :
- :impl<'a, T> Outputs<'a, T> {
- : /// Number of channels
- : pub fn len(&self) -> usize {
- /* <vst::buffer::Outputs<'a, T>>::len total: 1 9.8e-05 */
- : self.bufs.len()
- 1 9.8e-05 : }
- :
- : /// Returns true if the buffer is empty
- : pub fn is_empty(&self) -> bool {
- : self.len() == 0
- : }
- :
- : /// Access channel at the given index, unchecked
- : pub fn get(&self, i: usize) -> &'a [T] {
- : unsafe { slice::from_raw_parts(self.bufs[i], self.samples) }
- : }
- :
- : /// Mutably access channel at the given index, unchecked
- : pub fn get_mut(&self, i: usize) -> &'a mut [T] {
- : unsafe { slice::from_raw_parts_mut(self.bufs[i], self.samples) }
- : }
- :
- : /// Split borrowing at the given index, like for slices
- : pub fn split_at_mut(&mut self, i: usize) -> (Outputs<'a, T>, Outputs<'a, T>) {
- : let (l, r) = self.bufs.split_at(i);
- : (
- : Outputs {
- : bufs: l,
- : samples: self.samples,
- : },
- : Outputs {
- : bufs: r,
- : samples: self.samples,
- : },
- : )
- : }
- :}
- :
- :impl<'a, T> Index<usize> for Outputs<'a, T> {
- : type Output = [T];
- :
- : fn index(&self, i: usize) -> &Self::Output {
- : self.get(i)
- : }
- :}
- :
- :impl<'a, T> IndexMut<usize> for Outputs<'a, T> {
- : fn index_mut(&mut self, i: usize) -> &mut Self::Output {
- : self.get_mut(i)
- : }
- :}
- :
- :/// Iterator over buffers for output channels of an `AudioBuffer`.
- :pub struct OutputIterator<'a, T: 'a> {
- : data: Outputs<'a, T>,
- : i: usize,
- :}
- :
- :impl<'a, T> Iterator for OutputIterator<'a, T> {
- : type Item = &'a mut [T];
- :
- 2 2.0e-04 : fn next(&mut self) -> Option<Self::Item> {
- /* <vst::buffer::OutputIterator<'a, T> as core::iter::iterator::Iterator>::next total: 4 3.9e-04 */
- : if self.i < self.data.len() {
- 1 9.8e-05 : let val = self.data.get_mut(self.i);
- 1 9.8e-05 : self.i += 1;
- : Some(val)
- : } else {
- : None
- : }
- : }
- :}
- :
- :impl<'a, T: Sized> IntoIterator for Outputs<'a, T> {
- : type Item = &'a mut [T];
- : type IntoIter = OutputIterator<'a, T>;
- :
- 2 2.0e-04 : fn into_iter(self) -> Self::IntoIter {
- /* <vst::buffer::Outputs<'a, T> as core::iter::traits::IntoIterator>::into_iter total: 2 2.0e-04 */
- : OutputIterator { data: self, i: 0 }
- : }
- :}
- :
- :use event::{Event, MidiEvent};
- :use api;
- :use std::mem;
- :use std::borrow::Borrow;
- :
- :/// This buffer is used for sending midi events through the VST interface.
- :/// The purpose of this is to convert outgoing midi events from `event::Event` to `api::Events`.
- :/// It only allocates memory in new() and reuses the memory between calls.
- :pub struct SendEventBuffer {
- : buf: Vec<u8>,
- : api_events: Vec<api::SysExEvent>,
- :}
- :
- :impl Default for SendEventBuffer {
- : fn default() -> Self {
- : SendEventBuffer::new(1024)
- : }
- :}
- :
- :impl SendEventBuffer {
- : /// Creates a buffer for sending up to the given number of midi events per frame
- : #[inline]
- : pub fn new(capacity: usize) -> Self {
- : let header_size = mem::size_of::<api::Events>() - (mem::size_of::<*mut api::Event>() * 2);
- : let body_size = mem::size_of::<*mut api::Event>() * capacity;
- : let mut buf = vec![0u8; header_size + body_size];
- : let api_events = vec![unsafe { mem::zeroed::<api::SysExEvent>() }; capacity];
- : {
- : let ptrs = {
- : let e = Self::buf_as_api_events(&mut buf);
- : e.num_events = capacity as i32;
- : e.events_raw_mut()
- : };
- : for (ptr, event) in ptrs.iter_mut().zip(&api_events) {
- : let (ptr, event): (&mut *const api::SysExEvent, &api::SysExEvent) = (ptr, event);
- : *ptr = event;
- : }
- : }
- : Self {
- : buf: buf,
- : api_events: api_events,
- : }
- : }
- :
- : #[inline]
- : fn buf_as_api_events(buf: &mut [u8]) -> &mut api::Events {
- : unsafe { &mut *(buf.as_mut_ptr() as *mut api::Events) }
- : }
- :
- : /// Use this for sending events to a host or plugin.
- : ///
- : /// # Example
- : /// ```no_run
- : /// # use vst::plugin::{Info, Plugin, HostCallback};
- : /// # use vst::buffer::{AudioBuffer, SendEventBuffer};
- : /// # use vst::host::Host;
- : /// # struct ExamplePlugin { host: HostCallback, send_buffer: SendEventBuffer }
- : /// # impl Plugin for ExamplePlugin {
- : /// # fn get_info(&self) -> Info { Default::default() }
- : /// #
- : /// // Processor that clips samples above 0.4 or below -0.4:
- : /// fn process(&mut self, buffer: &mut AudioBuffer<f32>){
- : /// let events = vec![
- : /// // ...
- : /// ];
- : /// self.send_buffer.store(&events);
- : /// self.host.process_events(self.send_buffer.events());
- : /// }
- : /// # }
- : /// ```
- : pub fn store<'a, T: IntoIterator<Item = U>, U: Borrow<Event<'a>>>(&mut self, events: T) {
- : let count = events
- : .into_iter()
- : .zip(self.api_events.iter_mut())
- : .map(|(event, out)| {
- : let (event, out): (&Event, &mut api::SysExEvent) = (event.borrow(), out);
- : match *event {
- : Event::Midi(ev) => {
- : Self::store_midi_impl(out, &ev);
- : }
- : Event::SysEx(ev) => {
- : *out = api::SysExEvent {
- : event_type: api::EventType::SysEx,
- : byte_size: mem::size_of::<api::SysExEvent>() as i32,
- : delta_frames: ev.delta_frames,
- : _flags: 0,
- : data_size: ev.payload.len() as i32,
- : _reserved1: 0,
- : system_data: ev.payload.as_ptr() as *const u8 as *mut u8,
- : _reserved2: 0,
- : };
- : }
- : Event::Deprecated(e) => {
- : let out = unsafe { &mut *(out as *mut _ as *mut _) };
- : *out = e;
- : }
- : };
- : })
- : .count();
- : self.set_num_events(count);
- : }
- :
- : /// Use this for sending midi events to a host or plugin.
- : /// Like store() but for when you're not sending any SysExEvents, only MidiEvents.
- : pub fn store_midi<T: IntoIterator<Item = U>, U: Borrow<MidiEvent>>(&mut self, events: T) {
- : let count = events
- : .into_iter()
- : .zip(self.api_events.iter_mut())
- : .map(|(event, out)| {
- : let (ev, out): (&MidiEvent, &mut api::SysExEvent) = (event.borrow(), out);
- : Self::store_midi_impl(out, ev);
- : })
- : .count();
- : self.set_num_events(count);
- : }
- :
- : fn store_midi_impl(out: &mut api::SysExEvent, ev: &MidiEvent) {
- : use api::flags::REALTIME_EVENT;
- : let out = unsafe { &mut *(out as *mut _ as *mut _) };
- : *out = api::MidiEvent {
- : event_type: api::EventType::Midi,
- : byte_size: mem::size_of::<api::MidiEvent>() as i32,
- : delta_frames: ev.delta_frames,
- : flags: if ev.live { REALTIME_EVENT.bits() } else { 0 },
- : note_length: ev.note_length.unwrap_or(0),
- : note_offset: ev.note_offset.unwrap_or(0),
- : midi_data: ev.data,
- : _midi_reserved: 0,
- : detune: ev.detune,
- : note_off_velocity: ev.note_off_velocity,
- : _reserved1: 0,
- : _reserved2: 0,
- : };
- : }
- :
- : fn set_num_events(&mut self, events_len: usize) {
- : use std::cmp::min;
- : let e = Self::buf_as_api_events(&mut self.buf);
- : e.num_events = min(self.api_events.len(), events_len) as i32;
- : }
- :
- : /// Use this for sending midi events to a host or plugin.
- : /// See `store()`
- : #[inline]
- : pub fn events(&self) -> &api::Events {
- : unsafe { &*(self.buf.as_ptr() as *const api::Events) }
- : }
- :}
- :
- :#[cfg(test)]
- :mod tests {
- : use buffer::AudioBuffer;
- :
- : /// Size of buffers used in tests.
- : const SIZE: usize = 1024;
- :
- : /// Test that creating and zipping buffers works.
- : ///
- : /// This test creates a channel for 2 inputs and 2 outputs.
- : /// The input channels are simply values
- : /// from 0 to `SIZE-1` (e.g. [0, 1, 2, 3, 4, .. , SIZE - 1])
- : /// and the output channels are just 0.
- : /// This test assures that when the buffers are zipped together,
- : /// the input values do not change.
- : #[test]
- : fn buffer_zip() {
- : let in1: Vec<f32> = (0..SIZE).map(|x| x as f32).collect();
- : let in2 = in1.clone();
- :
- : let mut out1 = vec![0.0; SIZE];
- : let mut out2 = out1.clone();
- :
- : let inputs = vec![in1.as_ptr(), in2.as_ptr()];
- : let mut outputs = vec![out1.as_mut_ptr(), out2.as_mut_ptr()];
- : let mut buffer = AudioBuffer::new(&inputs, &mut outputs, SIZE);
- :
- : for (input, output) in buffer.zip() {
- : input.into_iter().zip(output.into_iter()).fold(0, |acc,
- : (input,
- : output)| {
- : assert_eq!(*input - acc as f32, 0.0);
- : assert_eq!(*output, 0.0);
- : acc + 1
- : });
- : }
- : }
- :
- : /// Test that creating buffers from raw pointers works.
- : #[test]
- : fn from_raw() {
- : let in1: Vec<f32> = (0..SIZE).map(|x| x as f32).collect();
- : let in2 = in1.clone();
- :
- : let mut out1 = vec![0.0; SIZE];
- : let mut out2 = out1.clone();
- :
- : let inputs = vec![in1.as_ptr(), in2.as_ptr()];
- : let mut outputs = vec![out1.as_mut_ptr(), out2.as_mut_ptr()];
- : let mut buffer =
- : unsafe { AudioBuffer::from_raw(2, 2, inputs.as_ptr(), outputs.as_mut_ptr(), SIZE) };
- :
- : for (input, output) in buffer.zip() {
- : input.into_iter().zip(output.into_iter()).fold(0, |acc,
- : (input,
- : output)| {
- : assert_eq!(*input - acc as f32, 0.0);
- : assert_eq!(*output, 0.0);
- : acc + 1
- : });
- : }
- : }
- :}
- /*
- * Total samples for file : "/build/gcc/src/gcc/libstdc++-v3/libsupc++/del_ops.cc"
- *
- * 9 8.8e-04
- */
- /* operator delete(void*, unsigned long) total: 9 8.8e-04 */
- /*
- * Total samples for file : "/home/cyrus/.cargo/registry/src/github.com-1ecc6299db9ec823/vst-0.0.1/src/interfaces.rs"
- *
- * 6 5.9e-04
- */
- ://! Function interfaces for VST 2.4 API.
- :
- :#![doc(hidden)]
- :
- :use std::{mem, slice};
- :
- :use std::os::raw::{c_char, c_void};
- :
- :use buffer::AudioBuffer;
- :use api::consts::*;
- :use api::{self, AEffect, ChannelProperties};
- :use editor::{Rect, KeyCode, Key, KnobMode};
- :use host::Host;
- :
- :/// Deprecated process function.
- :pub fn process_deprecated(
- : _effect: *mut AEffect,
- : _raw_inputs: *const *const f32,
- : _raw_outputs: *mut *mut f32,
- : _samples: i32,
- :) {
- :}
- :
- :/// VST2.4 replacing function.
- 3 2.9e-04 :pub fn process_replacing(
- /* vst::interfaces::process_replacing total: 6 5.9e-04 */
- : effect: *mut AEffect,
- : raw_inputs: *const *const f32,
- : raw_outputs: *mut *mut f32,
- : samples: i32,
- :) {
- : // Handle to the VST
- : let plugin = unsafe { (*effect).get_plugin() };
- : let cache = unsafe { (*effect).get_cache() };
- : let info = &mut cache.info;
- 2 2.0e-04 : let (input_count, output_count) = (info.inputs as usize, info.outputs as usize);
- : let mut buffer = unsafe {
- : AudioBuffer::from_raw(
- : input_count,
- : output_count,
- : raw_inputs,
- : raw_outputs,
- : samples as usize,
- : )
- : };
- : plugin.process(&mut buffer);
- 1 9.8e-05 :}
- :
- :/// VST2.4 replacing function with `f64` values.
- :pub fn process_replacing_f64(
- : effect: *mut AEffect,
- : raw_inputs: *const *const f64,
- : raw_outputs: *mut *mut f64,
- : samples: i32,
- :) {
- : let plugin = unsafe { (*effect).get_plugin() };
- : let cache = unsafe { (*effect).get_cache() };
- : let info = &mut cache.info;
- : let (input_count, output_count) = (info.inputs as usize, info.outputs as usize);
- : let mut buffer = unsafe {
- : AudioBuffer::from_raw(
- : input_count,
- : output_count,
- : raw_inputs,
- : raw_outputs,
- : samples as usize,
- : )
- : };
- : plugin.process_f64(&mut buffer);
- :}
- :
- :/// VST2.4 set parameter function.
- :pub fn set_parameter(effect: *mut AEffect, index: i32, value: f32) {
- : unsafe { (*effect).get_plugin() }.set_parameter(index, value);
- :}
- :
- :/// VST2.4 get parameter function.
- :pub fn get_parameter(effect: *mut AEffect, index: i32) -> f32 {
- : unsafe { (*effect).get_plugin() }.get_parameter(index)
- :}
- :
- :/// Copy a string into a destination buffer.
- :///
- :/// String will be cut at `max` characters.
- :fn copy_string(dst: *mut c_void, src: &str, max: usize) -> isize {
- : unsafe {
- : use std::cmp::min;
- : use libc::{c_void, memset, memcpy};
- :
- : let dst = dst as *mut c_void;
- : memset(dst, 0, max);
- : memcpy(dst, src.as_ptr() as *const c_void, min(max, src.len()));
- : }
- :
- : 1 // Success
- :}
- :
- :/// VST2.4 dispatch function. This function handles dispatching all opcodes to the VST plugin.
- :pub fn dispatch(
- : effect: *mut AEffect,
- : opcode: i32,
- : index: i32,
- : value: isize,
- : ptr: *mut c_void,
- : opt: f32,
- :) -> isize {
- : use plugin::{CanDo, OpCode};
- :
- : // Convert passed in opcode to enum
- : let opcode = OpCode::from(opcode);
- : // Plugin handle
- : let plugin = unsafe { (*effect).get_plugin() };
- :
- : match opcode {
- : OpCode::Initialize => plugin.init(),
- : OpCode::Shutdown => unsafe {
- : (*effect).drop_plugin();
- : drop(mem::transmute::<*mut AEffect, Box<AEffect>>(effect));
- : },
- :
- : OpCode::ChangePreset => plugin.change_preset(value as i32),
- : OpCode::GetCurrentPresetNum => return plugin.get_preset_num() as isize,
- : OpCode::SetCurrentPresetName => plugin.set_preset_name(read_string(ptr)),
- : OpCode::GetCurrentPresetName => {
- : let num = plugin.get_preset_num();
- : return copy_string(ptr, &plugin.get_preset_name(num), MAX_PRESET_NAME_LEN);
- : }
- :
- : OpCode::GetParameterLabel => {
- : return copy_string(ptr, &plugin.get_parameter_label(index), MAX_PARAM_STR_LEN)
- : }
- : OpCode::GetParameterDisplay => {
- : return copy_string(ptr, &plugin.get_parameter_text(index), MAX_PARAM_STR_LEN)
- : }
- : OpCode::GetParameterName => {
- : return copy_string(ptr, &plugin.get_parameter_name(index), MAX_PARAM_STR_LEN)
- : }
- :
- : OpCode::SetSampleRate => plugin.set_sample_rate(opt),
- : OpCode::SetBlockSize => plugin.set_block_size(value as i64),
- : OpCode::StateChanged => {
- : if value == 1 {
- : plugin.resume();
- : } else {
- : plugin.suspend();
- : }
- : }
- :
- : OpCode::EditorGetRect => {
- : if let Some(editor) = plugin.get_editor() {
- : let size = editor.size();
- : let pos = editor.position();
- :
- : unsafe {
- : // Given a Rect** structure
- : // TODO: Investigate whether we are given a valid Rect** pointer already
- : *(ptr as *mut *mut c_void) = Box::into_raw(Box::new(Rect {
- : left: pos.0 as i16, // x coord of position
- : top: pos.1 as i16, // y coord of position
- : right: (pos.0 + size.0) as i16, // x coord of pos + x coord of size
- : bottom: (pos.1 + size.1) as i16, // y coord of pos + y coord of size
- : })) as *mut _; // TODO: free memory
- : }
- : }
- : }
- : OpCode::EditorOpen => {
- : if let Some(editor) = plugin.get_editor() {
- : editor.open(ptr); //ptr is raw window handle, eg HWND* on windows
- : }
- : }
- : OpCode::EditorClose => {
- : if let Some(editor) = plugin.get_editor() {
- : editor.close();
- : }
- : }
- :
- : OpCode::EditorIdle => {
- : if let Some(editor) = plugin.get_editor() {
- : editor.idle();
- : }
- : }
- :
- : OpCode::GetData => {
- : let mut chunks = if index == 0 {
- : plugin.get_bank_data()
- : } else {
- : plugin.get_preset_data()
- : };
- :
- : chunks.shrink_to_fit();
- : let len = chunks.len() as isize; // eventually we should be using ffi::size_t
- :
- : unsafe {
- : *(ptr as *mut *mut c_void) = chunks.as_ptr() as *mut c_void;
- : }
- :
- : mem::forget(chunks);
- : return len;
- : }
- : OpCode::SetData => {
- : let chunks = unsafe { slice::from_raw_parts(ptr as *mut u8, value as usize) };
- :
- : if index == 0 {
- : plugin.load_bank_data(chunks);
- : } else {
- : plugin.load_preset_data(chunks);
- : }
- : }
- :
- : OpCode::ProcessEvents => {
- : plugin.process_events(unsafe { &*(ptr as *const api::Events) });
- : }
- : OpCode::CanBeAutomated => return plugin.can_be_automated(index) as isize,
- : OpCode::StringToParameter => {
- : return plugin.string_to_parameter(index, read_string(ptr)) as isize
- : }
- :
- : OpCode::GetPresetName => {
- : return copy_string(ptr, &plugin.get_preset_name(index), MAX_PRESET_NAME_LEN)
- : }
- :
- : OpCode::GetInputInfo => {
- : if index >= 0 && index < plugin.get_info().inputs {
- : unsafe {
- : let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
- : *ptr = plugin.get_input_info(index).into();
- : }
- : }
- : }
- : OpCode::GetOutputInfo => {
- : if index >= 0 && index < plugin.get_info().outputs {
- : unsafe {
- : let ptr = mem::transmute::<_, *mut ChannelProperties>(ptr);
- : *ptr = plugin.get_output_info(index).into();
- : }
- : }
- : }
- : OpCode::GetCategory => {
- : return plugin.get_info().category.into();
- : }
- :
- : OpCode::GetVendorName => {
- : return copy_string(ptr, &plugin.get_info().vendor, MAX_VENDOR_STR_LEN)
- : }
- : OpCode::GetProductName => {
- : return copy_string(ptr, &plugin.get_info().name, MAX_PRODUCT_STR_LEN)
- : }
- : OpCode::GetVendorVersion => return plugin.get_info().version as isize,
- : OpCode::VendorSpecific => return plugin.vendor_specific(index, value, ptr, opt),
- : OpCode::CanDo => {
- : let can_do: CanDo = match read_string(ptr).parse() {
- : Ok(c) => c,
- : Err(e) => {
- : warn!("{}", e);
- : return 0;
- : }
- : };
- : return plugin.can_do(can_do).into();
- : }
- : OpCode::GetTailSize => {
- : if plugin.get_tail_size() == 0 {
- : return 1;
- : } else {
- : return plugin.get_tail_size();
- : }
- : }
- :
- : //OpCode::GetParamInfo => { /*TODO*/ }
- : OpCode::GetApiVersion => return 2400,
- :
- : OpCode::EditorKeyDown => {
- : if let Some(editor) = plugin.get_editor() {
- : editor.key_down(KeyCode {
- : character: index as u8 as char,
- : key: Key::from(value),
- : modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8,
- : });
- : }
- : }
- : OpCode::EditorKeyUp => {
- : if let Some(editor) = plugin.get_editor() {
- : editor.key_up(KeyCode {
- : character: index as u8 as char,
- : key: Key::from(value),
- : modifier: unsafe { mem::transmute::<f32, i32>(opt) } as u8,
- : });
- : }
- : }
- : OpCode::EditorSetKnobMode => {
- : if let Some(editor) = plugin.get_editor() {
- : editor.set_knob_mode(KnobMode::from(value));
- : }
- : }
- :
- : _ => {
- : warn!("Unimplemented opcode ({:?})", opcode);
- : trace!(
- : "Arguments; index: {}, value: {}, ptr: {:?}, opt: {}",
- : index,
- : value,
- : ptr,
- : opt
- : );
- : }
- : }
- :
- : 0
- :}
- :
- :pub fn host_dispatch(
- : host: &mut Host,
- : effect: *mut AEffect,
- : opcode: i32,
- : index: i32,
- : value: isize,
- : ptr: *mut c_void,
- : opt: f32,
- :) -> isize {
- : use host::OpCode;
- :
- : match OpCode::from(opcode) {
- : OpCode::Version => return 2400,
- : OpCode::Automate => host.automate(index, opt),
- :
- : OpCode::Idle => host.idle(),
- :
- : // ...
- : OpCode::CanDo => {
- : info!("Plugin is asking if host can: {}.", read_string(ptr));
- : }
- :
- : OpCode::GetVendorVersion => return host.get_info().0,
- : OpCode::GetVendorString => return copy_string(ptr, &host.get_info().1, MAX_VENDOR_STR_LEN),
- : OpCode::GetProductString => {
- : return copy_string(ptr, &host.get_info().2, MAX_PRODUCT_STR_LEN)
- : }
- : OpCode::ProcessEvents => {
- : host.process_events(unsafe { &*(ptr as *const api::Events) });
- : }
- :
- : unimplemented => {
- : trace!("VST: Got unimplemented host opcode ({:?})", unimplemented);
- : trace!(
- : "Arguments; effect: {:?}, index: {}, value: {}, ptr: {:?}, opt: {}",
- : effect,
- : index,
- : value,
- : ptr,
- : opt
- : );
- : }
- : }
- : 0
- :}
- :
- :// Read a string from the `ptr` buffer
- :fn read_string(ptr: *mut c_void) -> String {
- : use std::ffi::CStr;
- :
- : String::from_utf8_lossy(unsafe { CStr::from_ptr(ptr as *mut c_char).to_bytes() }).into_owned()
- :}
- /*
- * Total samples for file : "/build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/ostream.tcc"
- *
- * 6 5.9e-04
- */
- /* std::ostream::sentry::sentry(std::ostream&) total: 5 4.9e-04 */
- /* std::ostream::flush() total: 1 9.8e-05 */
- /*
- * Total samples for file : "/build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/streambuf"
- *
- * 4 3.9e-04
- */
- /* std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::_M_pbump(char*, char*, long) total: 3 2.9e-04 */
- /*
- * Total samples for file : "/build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/ext/stdio_filebuf.h"
- *
- * 4 3.9e-04
- */
- /* __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char> >::sync() total: 3 2.9e-04 */
- /* __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char> >::xsputn(char const*, long) total: 1 9.8e-05 */
- /*
- * Total samples for file : "/build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_catch.cc"
- *
- * 2 2.0e-04
- */
- /* std::uncaught_exception() total: 2 2.0e-04 */
- /*
- * Total samples for file : "/build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/sstream.tcc"
- *
- * 2 2.0e-04
- */
- /* std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::_M_sync(char*, unsigned long, unsigned long) total: 2 2.0e-04 */
- /*
- * Total samples for file : "/build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/ostream_insert.h"
- *
- * 2 2.0e-04
- */
- /* std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) total: 3 2.9e-04 */
- /*
- * Total samples for file : "/home/cyrus/.cargo/registry/src/github.com-1ecc6299db9ec823/vst-0.0.1/src/api.rs"
- *
- * 1 9.8e-05
- */
- ://! Structures and types for interfacing with the VST 2.4 API.
- :
- :use std::os::raw::c_void;
- :
- :use plugin::Plugin;
- :use self::consts::*;
- :
- :/// Constant values
- :#[allow(missing_docs)] // For obvious constants
- :pub mod consts {
- :
- : pub const MAX_PRESET_NAME_LEN: usize = 24;
- : pub const MAX_PARAM_STR_LEN: usize = 32;
- : pub const MAX_LABEL: usize = 64;
- : pub const MAX_SHORT_LABEL: usize = 8;
- : pub const MAX_PRODUCT_STR_LEN: usize = 64;
- : pub const MAX_VENDOR_STR_LEN: usize = 64;
- :
- : /// VST plugins are identified by a magic number. This corresponds to 0x56737450.
- : pub const VST_MAGIC: i32 = ('V' as i32) << 24 | ('s' as i32) << 16 | ('t' as i32) << 8 |
- : ('P' as i32);
- :}
- :
- :/// `VSTPluginMain` function signature.
- :pub type PluginMain = fn(callback: HostCallbackProc) -> *mut AEffect;
- :
- :/// Host callback function passed to plugin.
- :/// Can be used to query host information from plugin side.
- :pub type HostCallbackProc = fn(effect: *mut AEffect,
- : opcode: i32,
- : index: i32,
- : value: isize,
- : ptr: *mut c_void,
- : opt: f32)
- : -> isize;
- :
- :/// Dispatcher function used to process opcodes. Called by host.
- :pub type DispatcherProc = fn(effect: *mut AEffect,
- : opcode: i32,
- : index: i32,
- : value: isize,
- : ptr: *mut c_void,
- : opt: f32)
- : -> isize;
- :
- :/// Process function used to process 32 bit floating point samples. Called by host.
- :pub type ProcessProc = fn(effect: *mut AEffect,
- : inputs: *const *const f32,
- : outputs: *mut *mut f32,
- : sample_frames: i32);
- :
- :/// Process function used to process 64 bit floating point samples. Called by host.
- :pub type ProcessProcF64 = fn(effect: *mut AEffect,
- : inputs: *const *const f64,
- : outputs: *mut *mut f64,
- : sample_frames: i32);
- :
- :/// Callback function used to set parameter values. Called by host.
- :pub type SetParameterProc = fn(effect: *mut AEffect, index: i32, parameter: f32);
- :
- :/// Callback function used to get parameter values. Called by host.
- :pub type GetParameterProc = fn(effect: *mut AEffect, index: i32) -> f32;
- :
- :/// Used with the VST API to pass around plugin information.
- :#[allow(non_snake_case)]
- :#[repr(C)]
- :pub struct AEffect {
- : /// Magic number. Must be `['V', 'S', 'T', 'P']`.
- : pub magic: i32,
- :
- : /// Host to plug-in dispatcher.
- : pub dispatcher: DispatcherProc,
- :
- : /// Accumulating process mode is deprecated in VST 2.4! Use `processReplacing` instead!
- : pub _process: ProcessProc,
- :
- : /// Set value of automatable parameter.
- : pub setParameter: SetParameterProc,
- :
- : /// Get value of automatable parameter.
- : pub getParameter: GetParameterProc,
- :
- : /// Number of programs (Presets).
- : pub numPrograms: i32,
- :
- : /// Number of parameters. All programs are assumed to have this many parameters.
- : pub numParams: i32,
- :
- : /// Number of audio inputs.
- : pub numInputs: i32,
- :
- : /// Number of audio outputs.
- : pub numOutputs: i32,
- :
- : /// Bitmask made of values from api::flags.
- : ///
- : /// ```no_run
- : /// use vst::api::flags;
- : /// let flags = flags::CAN_REPLACING | flags::CAN_DOUBLE_REPLACING;
- : /// // ...
- : /// ```
- : pub flags: i32,
- :
- : /// Reserved for host, must be 0.
- : pub reserved1: isize,
- :
- : /// Reserved for host, must be 0.
- : pub reserved2: isize,
- :
- : /// For algorithms which need input in the first place (Group delay or latency in samples).
- : ///
- : /// This value should be initially in a resume state.
- : pub initialDelay: i32,
- :
- : /// Deprecated unused member.
- : pub _realQualities: i32,
- :
- : /// Deprecated unused member.
- : pub _offQualities: i32,
- :
- : /// Deprecated unused member.
- : pub _ioRatio: f32,
- :
- : /// Void pointer usable by api to store object data.
- : pub object: *mut c_void,
- :
- : /// User defined pointer.
- : pub user: *mut c_void,
- :
- : /// Registered unique identifier (register it at Steinberg 3rd party support Web).
- : /// This is used to identify a plug-in during save+load of preset and project.
- : pub uniqueId: i32,
- :
- : /// Plug-in version (e.g. 1100 for v1.1.0.0).
- : pub version: i32,
- :
- : /// Process audio samples in replacing mode.
- : pub processReplacing: ProcessProc,
- :
- : /// Process double-precision audio samples in replacing mode.
- : pub processReplacingF64: ProcessProcF64,
- :
- : /// Reserved for future use (please zero).
- : pub future: [u8; 56],
- :}
- :
- :impl AEffect {
- : /// Return handle to Plugin object. Only works for plugins created using this library.
- : // Supresses warning about returning a reference to a box
- : #[allow(unknown_lints)]
- : #[allow(borrowed_box)]
- 1 9.8e-05 : pub unsafe fn get_plugin(&mut self) -> &mut Box<Plugin> {
- /* vst::api::AEffect::get_plugin total: 1 9.8e-05 */
- : //FIXME: find a way to do this without resorting to transmuting via a box
- : &mut *(self.object as *mut Box<Plugin>)
- : }
- :
- : /// Drop the Plugin object. Only works for plugins created using this library.
- : pub unsafe fn drop_plugin(&mut self) {
- : drop(Box::from_raw(self.object as *mut Box<Plugin>));
- : drop(Box::from_raw(self.user as *mut super::PluginCache));
- : }
- :
- : pub(crate) unsafe fn get_cache(&mut self) -> &mut super::PluginCache {
- : &mut *(self.user as *mut _)
- : }
- :}
- :
- :/// Information about a channel. Only some hosts use this information.
- :#[repr(C)]
- :pub struct ChannelProperties {
- : /// Channel name.
- : pub name: [u8; MAX_LABEL as usize],
- :
- : /// Flags found in `channel_flags` module.
- : pub flags: i32,
- :
- : /// Type of speaker arrangement this channel is a part of.
- : pub arrangement_type: SpeakerArrangementType,
- :
- : /// Name of channel (recommended: 6 characters + delimiter).
- : pub short_name: [u8; MAX_SHORT_LABEL as usize],
- :
- : /// Reserved for future use.
- : pub future: [u8; 48],
- :}
- :
- :/// Tells the host how the channels are intended to be used in the plugin. Only useful for some
- :/// hosts.
- :#[repr(i32)]
- :#[derive(Clone, Copy)]
- :pub enum SpeakerArrangementType {
- : /// User defined arrangement.
- : Custom = -2,
- : /// Empty arrangement.
- : Empty = -1,
- :
- : /// Mono.
- : Mono = 0,
- :
- : /// L R
- : Stereo,
- : /// Ls Rs
- : StereoSurround,
- : /// Lc Rc
- : StereoCenter,
- : /// Sl Sr
- : StereoSide,
- : /// C Lfe
- : StereoCLfe,
- :
- : /// L R C
- : Cinema30,
- : /// L R S
- : Music30,
- :
- : /// L R C Lfe
- : Cinema31,
- : /// L R Lfe S
- : Music31,
- :
- : /// L R C S (LCRS)
- : Cinema40,
- : /// L R Ls Rs (Quadro)
- : Music40,
- :
- : /// L R C Lfe S (LCRS + Lfe)
- : Cinema41,
- : /// L R Lfe Ls Rs (Quadro + Lfe)
- : Music41,
- :
- : /// L R C Ls Rs
- : Surround50,
- : /// L R C Lfe Ls Rs
- : Surround51,
- :
- : /// L R C Ls Rs Cs
- : Cinema60,
- : /// L R Ls Rs Sl Sr
- : Music60,
- :
- : /// L R C Lfe Ls Rs Cs
- : Cinema61,
- : /// L R Lfe Ls Rs Sl Sr
- : Music61,
- :
- : /// L R C Ls Rs Lc Rc
- : Cinema70,
- : /// L R C Ls Rs Sl Sr
- : Music70,
- :
- : /// L R C Lfe Ls Rs Lc Rc
- : Cinema71,
- : /// L R C Lfe Ls Rs Sl Sr
- : Music71,
- :
- : /// L R C Ls Rs Lc Rc Cs
- : Cinema80,
- : /// L R C Ls Rs Cs Sl Sr
- : Music80,
- :
- : /// L R C Lfe Ls Rs Lc Rc Cs
- : Cinema81,
- : /// L R C Lfe Ls Rs Cs Sl Sr
- : Music81,
- :
- : /// L R C Lfe Ls Rs Tfl Tfc Tfr Trl Trr Lfe2
- : Surround102,
- :}
- :
- :/// Used to specify whether functionality is supported.
- :#[allow(missing_docs)]
- :pub enum Supported {
- : Yes,
- : Maybe,
- : No,
- :}
- :
- :impl Supported {
- : /// Create a `Supported` value from an integer if possible.
- : pub fn from(val: isize) -> Option<Supported> {
- : use self::Supported::*;
- :
- : match val {
- : 1 => Some(Yes),
- : 0 => Some(Maybe),
- : -1 => Some(No),
- : _ => None,
- : }
- : }
- :}
- :
- :impl Into<isize> for Supported {
- : /// Convert to integer ordinal for interop with VST api.
- : fn into(self) -> isize {
- : use self::Supported::*;
- :
- : match self {
- : Yes => 1,
- : Maybe => 0,
- : No => -1,
- : }
- : }
- :}
- :
- :/// Denotes in which thread the host is in.
- :#[repr(i32)]
- :pub enum ProcessLevel {
- : /// Unsupported by host.
- : Unknown = 0,
- :
- : /// GUI thread.
- : User,
- : /// Audio process thread.
- : Realtime,
- : /// Sequence thread (MIDI, etc).
- : Prefetch,
- : /// Offline processing thread (therefore GUI/user thread).
- : Offline,
- :}
- :
- :/// Language that the host is using.
- :#[repr(i32)]
- :#[allow(missing_docs)]
- :pub enum HostLanguage {
- : English = 1,
- : German,
- : French,
- : Italian,
- : Spanish,
- : Japanese,
- :}
- :
- :/// The file operation to perform.
- :#[repr(i32)]
- :pub enum FileSelectCommand {
- : /// Load a file.
- : Load = 0,
- : /// Save a file.
- : Save,
- : /// Load multiple files simultaneously.
- : LoadMultipleFiles,
- : /// Choose a directory.
- : SelectDirectory,
- :}
- :
- :// TODO: investigate removing this.
- :/// Format to select files.
- :pub enum FileSelectType {
- : /// Regular file selector.
- : Regular,
- :}
- :
- :/// File type descriptor.
- :#[repr(C)]
- :pub struct FileType {
- : /// Display name of file type.
- : pub name: [u8; 128],
- :
- : /// OS X file type.
- : pub osx_type: [u8; 8],
- : /// Windows file type.
- : pub win_type: [u8; 8],
- : /// Unix file type.
- : pub nix_type: [u8; 8],
- :
- : /// MIME type.
- : pub mime_type_1: [u8; 128],
- : /// Additional MIME type.
- : pub mime_type_2: [u8; 128],
- :}
- :
- :/// File selector descriptor used in `host::OpCode::OpenFileSelector`.
- :#[repr(C)]
- :pub struct FileSelect {
- : /// The type of file selection to perform.
- : pub command: FileSelectCommand,
- : /// The file selector to open.
- : pub select_type: FileSelectType,
- : /// Unknown. 0 = no creator.
- : pub mac_creator: i32,
- : /// Number of file types.
- : pub num_types: i32,
- : /// List of file types to show.
- : pub file_types: *mut FileType,
- :
- : /// File selector's title.
- : pub title: [u8; 1024],
- : /// Initial path.
- : pub initial_path: *mut u8,
- : /// Used when operation returns a single path.
- : pub return_path: *mut u8,
- : /// Size of the path buffer in bytes.
- : pub size_return_path: i32,
- :
- : /// Used when operation returns multiple paths.
- : pub return_multiple_paths: *mut *mut u8,
- : /// Number of paths returned.
- : pub num_paths: i32,
- :
- : /// Reserved by host.
- : pub reserved: isize,
- : /// Reserved for future use.
- : pub future: [u8; 116],
- :}
- :
- :/// A struct which contains events.
- :#[repr(C)]
- :pub struct Events {
- : /// Number of events.
- : pub num_events: i32,
- :
- : /// Reserved for future use. Should be 0.
- : pub _reserved: isize,
- :
- : /// Variable-length array of pointers to `api::Event` objects.
- : ///
- : /// The VST standard specifies a variable length array of initial size 2. If there are more
- : /// than 2 elements a larger array must be stored in this structure.
- : pub events: [*mut Event; 2],
- :}
- :
- :impl Events {
- : #[inline]
- : pub(crate) fn events_raw(&self) -> &[*const Event] {
- : use std::slice;
- : unsafe {
- : slice::from_raw_parts(
- : &self.events[0] as *const *mut _ as *const *const _,
- : self.num_events as usize,
- : )
- : }
- : }
- :
- : #[inline]
- : pub(crate) fn events_raw_mut(&mut self) -> &mut [*const SysExEvent] {
- : use std::slice;
- : unsafe {
- : slice::from_raw_parts_mut(
- : &mut self.events[0] as *mut *mut _ as *mut *const _,
- : self.num_events as usize,
- : )
- : }
- : }
- :
- : /// Use this in your impl of process_events() to process the incoming midi events.
- : ///
- : /// # Example
- : /// ```no_run
- : /// # use vst::plugin::{Info, Plugin, HostCallback};
- : /// # use vst::buffer::{AudioBuffer, SendEventBuffer};
- : /// # use vst::host::Host;
- : /// # use vst::api;
- : /// # use vst::event::{Event, MidiEvent};
- : /// # struct ExamplePlugin { host: HostCallback, send_buf: SendEventBuffer }
- : /// # impl Plugin for ExamplePlugin {
- : /// # fn get_info(&self) -> Info { Default::default() }
- : /// #
- : /// fn process_events(&mut self, events: &api::Events) {
- : /// for e in events.events() {
- : /// match e {
- : /// Event::Midi(MidiEvent { data, .. }) => {
- : /// // ...
- : /// }
- : /// _ => ()
- : /// }
- : /// }
- : /// }
- : /// # }
- : /// ```
- : #[inline]
- : pub fn events(&self) -> EventIterator {
- : EventIterator {
- : events: self.events_raw(),
- : index: 0,
- : }
- : }
- :}
- :
- :/// An iterator over events, returned by `api::Events::events`
- :pub struct EventIterator<'a> {
- : events: &'a [*const Event],
- : index: usize,
- :}
- :
- :impl<'a> Iterator for EventIterator<'a> {
- : type Item = ::event::Event<'a>;
- :
- : fn next(&mut self) -> Option<Self::Item> {
- : let index = self.index;
- : if index < self.events.len() {
- : self.index += 1;
- : Some(::event::Event::from(unsafe { *self.events[index] }))
- : } else {
- : None
- : }
- : }
- :}
- :
- :/// The type of event that has occured. See `api::Event.event_type`.
- :#[repr(i32)]
- :#[derive(Copy, Clone, Debug)]
- :pub enum EventType {
- : /// Midi event. See `api::MidiEvent`.
- : Midi = 1,
- :
- : /// Deprecated.
- : _Audio,
- : /// Deprecated.
- : _Video,
- : /// Deprecated.
- : _Parameter,
- : /// Deprecated.
- : _Trigger,
- :
- : /// System exclusive event. See `api::SysExEvent`.
- : SysEx,
- :}
- :
- :/// A VST event intended to be casted to a corresponding type.
- :///
- :/// The event types are not all guaranteed to be the same size,
- :/// so casting between them can be done
- :/// via `mem::transmute()` while leveraging pointers, e.g.
- :///
- :/// ```
- :/// # use vst::api::{Event, EventType, MidiEvent, SysExEvent};
- :/// # let mut event: *mut Event = &mut unsafe { std::mem::zeroed() };
- :/// // let event: *const Event = ...;
- :/// let midi_event: &MidiEvent = unsafe { std::mem::transmute(event) };
- :/// ```
- :#[repr(C)]
- :#[derive(Copy, Clone)]
- :pub struct Event {
- : /// The type of event. This lets you know which event this object should be casted to.
- : ///
- : /// # Example
- : ///
- : /// ```
- : /// # use vst::api::{Event, EventType, MidiEvent, SysExEvent};
- : /// #
- : /// # // Valid for test
- : /// # let mut event: *mut Event = &mut unsafe { std::mem::zeroed() };
- : /// #
- : /// // let mut event: *mut Event = ...
- : /// match unsafe { (*event).event_type } {
- : /// EventType::Midi => {
- : /// let midi_event: &MidiEvent = unsafe {
- : /// std::mem::transmute(event)
- : /// };
- : ///
- : /// // ...
- : /// }
- : /// EventType::SysEx => {
- : /// let sys_event: &SysExEvent = unsafe {
- : /// std::mem::transmute(event)
- : /// };
- : ///
- : /// // ...
- : /// }
- : /// // ...
- : /// # _ => {}
- : /// }
- : /// ```
- : pub event_type: EventType,
- :
- : /// Size of this structure; `mem::sizeof::<Event>()`.
- : pub byte_size: i32,
- :
- : /// Number of samples into the current processing block that this event occurs on.
- : ///
- : /// E.g. if the block size is 512 and this value is 123, the event will occur on sample
- : /// `samples[123]`.
- : pub delta_frames: i32,
- :
- : /// Generic flags, none defined in VST api yet.
- : pub _flags: i32,
- :
- : /// The `Event` type is cast appropriately, so this acts as reserved space.
- : ///
- : /// The actual size of the data may vary
- : ///as this type is not guaranteed to be the same size as the other event types.
- : pub _reserved: [u8; 16],
- :}
- :
- :/// A midi event.
- :#[repr(C)]
- :pub struct MidiEvent {
- : /// Should be `EventType::Midi`.
- : pub event_type: EventType,
- :
- : /// Size of this structure; `mem::sizeof::<MidiEvent>()`.
- : pub byte_size: i32,
- :
- : /// Number of samples into the current processing block that this event occurs on.
- : ///
- : /// E.g. if the block size is 512 and this value is 123, the event will occur on sample
- : /// `samples[123]`.
- : pub delta_frames: i32,
- :
- : /// See `flags::MidiFlags`.
- : pub flags: i32,
- :
- : /// Length in sample frames of entire note if available, otherwise 0.
- : pub note_length: i32,
- :
- : /// Offset in samples into note from start if available, otherwise 0.
- : pub note_offset: i32,
- :
- : /// 1 to 3 midi bytes. TODO: Doc
- : pub midi_data: [u8; 3],
- :
- : /// Reserved midi byte (0).
- : pub _midi_reserved: u8,
- :
- : /// Detuning between -63 and +64 cents,
- : /// for scales other than 'well-tempered'. e.g. 'microtuning'
- : pub detune: i8,
- :
- : /// Note off velocity between 0 and 127.
- : pub note_off_velocity: u8,
- :
- : /// Reserved for future use. Should be 0.
- : pub _reserved1: u8,
- : /// Reserved for future use. Should be 0.
- : pub _reserved2: u8,
- :}
- :
- :/// A midi system exclusive event.
- :///
- :/// This event only contains raw byte data, and is up to the plugin to interpret it correctly.
- :/// `plugin::CanDo` has a `ReceiveSysExEvent` variant which lets the host query the plugin as to
- :/// whether this event is supported.
- :#[repr(C)]
- :#[derive(Clone)]
- :pub struct SysExEvent {
- : /// Should be `EventType::SysEx`.
- : pub event_type: EventType,
- :
- : /// Size of this structure; `mem::sizeof::<SysExEvent>()`.
- : pub byte_size: i32,
- :
- : /// Number of samples into the current processing block that this event occurs on.
- : ///
- : /// E.g. if the block size is 512 and this value is 123, the event will occur on sample
- : /// `samples[123]`.
- : pub delta_frames: i32,
- :
- : /// Generic flags, none defined in VST api yet.
- : pub _flags: i32,
- :
- : /// Size of payload in bytes.
- : pub data_size: i32,
- :
- : /// Reserved for future use. Should be 0.
- : pub _reserved1: isize,
- :
- : /// Pointer to payload.
- : pub system_data: *mut u8,
- :
- : /// Reserved for future use. Should be 0.
- : pub _reserved2: isize,
- :}
- :
- :/// Bitflags.
- :pub mod flags {
- : bitflags! {
- : /// Flags for VST channels.
- : pub flags Channel: i32 {
- : /// Indicates channel is active. Ignored by host.
- : const ACTIVE = 1,
- : /// Indicates channel is first of stereo pair.
- : const STEREO = 1 << 1,
- : /// Use channel's specified speaker_arrangement instead of stereo flag.
- : const SPEAKER = 1 << 2
- : }
- : }
- :
- : bitflags! {
- : /// Flags for VST plugins.
- : pub flags Plugin: i32 {
- : /// Plugin has an editor.
- : const HAS_EDITOR = 1,
- : /// Plugin can process 32 bit audio. (Mandatory in VST 2.4).
- : const CAN_REPLACING = 1 << 4,
- : /// Plugin preset data is handled in formatless chunks.
- : const PROGRAM_CHUNKS = 1 << 5,
- : /// Plugin is a synth.
- : const IS_SYNTH = 1 << 8,
- : /// Plugin does not produce sound when all input is silence.
- : const NO_SOUND_IN_STOP = 1 << 9,
- : /// Supports 64 bit audio processing.
- : const CAN_DOUBLE_REPLACING = 1 << 12
- : }
- : }
- :
- : bitflags!{
- : /// Cross platform modifier key flags.
- : pub flags ModifierKey: u8 {
- : /// Shift key.
- : const SHIFT = 1,
- : /// Alt key.
- : const ALT = 1 << 1,
- : /// Control on mac.
- : const COMMAND = 1 << 2,
- : /// Command on mac, ctrl on other.
- : const CONTROL = 1 << 3, // Ctrl on PC, Apple on Mac
- : }
- : }
- :
- : bitflags! {
- : /// MIDI event flags.
- : pub flags MidiEvent: i32 {
- : /// This event is played live (not in playback from a sequencer track). This allows the
- : /// plugin to handle these flagged events with higher priority, especially when the
- : /// plugin has a big latency as per `plugin::Info::initial_delay`.
- : const REALTIME_EVENT = 1,
- : }
- : }
- :}
- /*
- * Total samples for file : "/build/gcc/src/gcc/libstdc++-v3/src/c++98/tree.cc"
- *
- * 1 9.8e-05
- */
- /* std::local_Rb_tree_decrement(std::_Rb_tree_node_base*) total: 1 9.8e-05 */
- /*
- * Total samples for file : "/build/gcc/src/gcc/libstdc++-v3/src/c++11/chrono.cc"
- *
- * 1 9.8e-05
- */
- /* std::chrono::_V2::system_clock::now() total: 1 9.8e-05 */
- /*
- * Total samples for file : "/build/gcc/src/gcc/libstdc++-v3/libsupc++/tinfo.h"
- *
- * 1 9.8e-05
- */
- /*
- * Total samples for file : "/build/gcc/src/gcc/libstdc++-v3/libsupc++/del_opv.cc"
- *
- * 1 9.8e-05
- */
- /* operator delete[](void*) total: 1 9.8e-05 */
- /*
- * Total samples for file : "/build/gcc/src/gcc-build/gcc/include/cpuid.h"
- *
- * 1 9.8e-05
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement