|
| 1 | +use crate::port::PortType; |
| 2 | +use std::cell::Cell; |
| 3 | +use std::ffi::c_void; |
| 4 | +use std::ptr::NonNull; |
| 5 | +use urid::UriBound; |
| 6 | + |
| 7 | +/// A port connected to an array of float audio samples. Using this port **requires** the `inPlaceBroken` feature. |
| 8 | +/// |
| 9 | +/// Ports of this type are connected to a buffer of float audio samples, represented as a slice. |
| 10 | +/// |
| 11 | +/// Audio samples are normalized between -1.0 and 1.0, though there is no requirement for samples to be strictly within this range. |
| 12 | +/// |
| 13 | +/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information. |
| 14 | +/// |
| 15 | +/// # Example |
| 16 | +/// |
| 17 | +/// This very simple amplifier plugin multiplies the input sample by 2 and outputs the result. |
| 18 | +/// |
| 19 | +/// ``` |
| 20 | +/// # use lv2_core::prelude::*; |
| 21 | +/// # use urid::*; |
| 22 | +/// # #[uri("http://lv2plug.in/plugins.rs/simple_amp")] |
| 23 | +/// # struct SimpleAmp; |
| 24 | +/// #[derive(PortCollection)] |
| 25 | +/// struct SimpleAmpPorts { |
| 26 | +/// input: InputPort<Audio>, |
| 27 | +/// output: OutputPort<Audio>, |
| 28 | +/// } |
| 29 | +/// |
| 30 | +/// impl Plugin for SimpleAmp { |
| 31 | +/// type Ports = SimpleAmpPorts; |
| 32 | +/// # type InitFeatures = (); |
| 33 | +/// # type AudioFeatures = (); |
| 34 | +/// # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> { |
| 35 | +/// # unimplemented!() |
| 36 | +/// # } |
| 37 | +/// // some implementation details elided… |
| 38 | +/// |
| 39 | +/// fn run(&mut self, ports: &mut SimpleAmpPorts, _: &mut (), _: u32) { |
| 40 | +/// // Input and Output dereference to `&[f32]` and `&mut [f32]`, respectively. |
| 41 | +/// let input = ports.input.iter(); |
| 42 | +/// let output = ports.output.iter_mut(); |
| 43 | +/// |
| 44 | +/// for (input_sample, output_sample) in input.zip(output) { |
| 45 | +/// *output_sample = *input_sample * 2.0; |
| 46 | +/// } |
| 47 | +/// } |
| 48 | +/// } |
| 49 | +/// |
| 50 | +/// |
| 51 | +/// ``` |
| 52 | +/// |
| 53 | +/// # Safety |
| 54 | +/// |
| 55 | +/// Using this port type requires the `inPlaceBroken` LV2 feature in your plugin. Because this port |
| 56 | +/// type uses shared (`&[f32]`) and exclusive (`&mut [f32]`) references to its data, LV2 hosts |
| 57 | +/// MUST NOT use the same buffer for both the input and the output. |
| 58 | +/// However, do note that some hosts (Ardour, Zrythm, etc.) do not support `inPlaceBroken` plugins. |
| 59 | +/// |
| 60 | +/// Use [`InPlaceAudio`] instead if you do not want to enforce this restriction on hosts, |
| 61 | +/// and do not need references pointing into the buffer's contents. |
| 62 | +pub struct Audio; |
| 63 | + |
| 64 | +unsafe impl UriBound for Audio { |
| 65 | + const URI: &'static [u8] = ::lv2_sys::LV2_CORE__AudioPort; |
| 66 | +} |
| 67 | + |
| 68 | +impl PortType for Audio { |
| 69 | + type InputPortType = &'static [f32]; |
| 70 | + type OutputPortType = &'static mut [f32]; |
| 71 | + |
| 72 | + #[inline] |
| 73 | + unsafe fn input_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::InputPortType { |
| 74 | + std::slice::from_raw_parts(pointer.as_ptr() as *const f32, sample_count as usize) |
| 75 | + } |
| 76 | + |
| 77 | + #[inline] |
| 78 | + unsafe fn output_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::OutputPortType { |
| 79 | + std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut f32, sample_count as usize) |
| 80 | + } |
| 81 | +} |
| 82 | + |
| 83 | +/// A port connected to an array of float audio samples. This port type can safely operate on shared input and output buffers. |
| 84 | +/// |
| 85 | +/// Ports of this type are connected to a buffer of float audio samples, represented as a slice of [`Cell`s](std::cell::Cell). |
| 86 | +/// |
| 87 | +/// Audio samples are normalized between -1.0 and 1.0, though there is no requirement for samples to be strictly within this range. |
| 88 | +/// |
| 89 | +/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information. |
| 90 | +/// |
| 91 | +/// # Example |
| 92 | +/// |
| 93 | +/// This very simple amplifier plugin multiplies the input sample by 2 and outputs the result. |
| 94 | +/// |
| 95 | +/// ``` |
| 96 | +/// # use lv2_core::prelude::*; |
| 97 | +/// # use urid::*; |
| 98 | +/// # #[uri("http://lv2plug.in/plugins.rs/simple_amp")] |
| 99 | +/// # struct SimpleAmp; |
| 100 | +/// #[derive(PortCollection)] |
| 101 | +/// struct SimpleAmpPorts { |
| 102 | +/// input: InputPort<InPlaceAudio>, |
| 103 | +/// output: OutputPort<InPlaceAudio>, |
| 104 | +/// } |
| 105 | +/// |
| 106 | +/// impl Plugin for SimpleAmp { |
| 107 | +/// type Ports = SimpleAmpPorts; |
| 108 | +/// # type InitFeatures = (); |
| 109 | +/// # type AudioFeatures = (); |
| 110 | +/// # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> { |
| 111 | +/// # unimplemented!() |
| 112 | +/// # } |
| 113 | +/// // some implementation details elided… |
| 114 | +/// |
| 115 | +/// fn run(&mut self, ports: &mut SimpleAmpPorts, _: &mut (), _: u32) { |
| 116 | +/// // Input and Output both dereference to `&[Cell<f32>]`. |
| 117 | +/// let input = ports.input.iter(); |
| 118 | +/// let output = ports.output.iter(); |
| 119 | +/// |
| 120 | +/// for (input_sample, output_sample) in input.zip(output) { |
| 121 | +/// output_sample.set(input_sample.get() * 2.0); |
| 122 | +/// } |
| 123 | +/// } |
| 124 | +/// } |
| 125 | +/// |
| 126 | +/// |
| 127 | +/// ``` |
| 128 | +pub struct InPlaceAudio; |
| 129 | + |
| 130 | +unsafe impl UriBound for InPlaceAudio { |
| 131 | + const URI: &'static [u8] = ::lv2_sys::LV2_CORE__AudioPort; |
| 132 | +} |
| 133 | + |
| 134 | +impl PortType for InPlaceAudio { |
| 135 | + type InputPortType = &'static [Cell<f32>]; |
| 136 | + type OutputPortType = &'static [Cell<f32>]; |
| 137 | + |
| 138 | + #[inline] |
| 139 | + unsafe fn input_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::InputPortType { |
| 140 | + Cell::from_mut(std::slice::from_raw_parts_mut( |
| 141 | + pointer.as_ptr() as *mut f32, |
| 142 | + sample_count as usize, |
| 143 | + )) |
| 144 | + .as_slice_of_cells() |
| 145 | + } |
| 146 | + |
| 147 | + #[inline] |
| 148 | + unsafe fn output_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::OutputPortType { |
| 149 | + Cell::from_mut(std::slice::from_raw_parts_mut( |
| 150 | + pointer.as_ptr() as *mut f32, |
| 151 | + sample_count as usize, |
| 152 | + )) |
| 153 | + .as_slice_of_cells() |
| 154 | + } |
| 155 | +} |
0 commit comments