Skip to main content

clack_plugin/process/audio/
output.rs

1use crate::internal_utils::{slice_from_external_parts, slice_from_external_parts_mut};
2use crate::prelude::Audio;
3use crate::process::InputChannelsIter;
4use crate::process::audio::{BufferError, SampleType};
5use clack_common::process::ConstantMask;
6use clap_sys::audio_buffer::clap_audio_buffer;
7use std::slice::IterMut;
8
9/// An iterator of all the available [`OutputPort`]s from an [`Audio`] struct.
10pub struct OutputPortsIter<'a> {
11    outputs: IterMut<'a, clap_audio_buffer>,
12    frames_count: u32,
13}
14
15impl<'a> OutputPortsIter<'a> {
16    #[inline]
17    pub(crate) fn new(audio: &'a mut Audio<'_>) -> Self {
18        Self {
19            outputs: audio.outputs.iter_mut(),
20            frames_count: audio.frames_count,
21        }
22    }
23}
24
25impl<'a> Iterator for OutputPortsIter<'a> {
26    type Item = OutputPort<'a>;
27
28    #[inline]
29    fn next(&mut self) -> Option<Self::Item> {
30        self.outputs
31            .next()
32            // SAFETY: The Audio type this is built from ensures each buffer is valid
33            // and is of length frames_count.
34            .map(|buf| unsafe { OutputPort::from_raw(buf, self.frames_count) })
35    }
36
37    #[inline]
38    fn size_hint(&self) -> (usize, Option<usize>) {
39        self.outputs.size_hint()
40    }
41}
42
43impl ExactSizeIterator for OutputPortsIter<'_> {
44    #[inline]
45    fn len(&self) -> usize {
46        self.outputs.len()
47    }
48}
49
50/// An output audio port.
51pub struct OutputPort<'a> {
52    inner: &'a mut clap_audio_buffer,
53    frames_count: u32,
54}
55
56impl<'a> OutputPort<'a> {
57    /// # Safety
58    ///
59    /// * The provided buffer must be valid;
60    /// * `frames_count` *must* match the size of the buffers.
61    #[inline]
62    pub(crate) unsafe fn from_raw(inner: &'a mut clap_audio_buffer, frames_count: u32) -> Self {
63        Self {
64            inner,
65            frames_count,
66        }
67    }
68
69    /// Retrieves the output port's channels.
70    ///
71    /// Because each port can hold either [`f32`] or [`f64`] sample data, this method returns a
72    /// [`SampleType`] enum of the input channels, to indicate which one the port holds.
73    ///
74    /// # Errors
75    ///
76    /// This method returns a [`BufferError::InvalidChannelBuffer`] if the host provided neither
77    /// [`f32`] or [`f64`] buffer type, which is invalid per the CLAP specification.
78    ///
79    /// # Example
80    ///
81    /// ```
82    /// use clack_plugin::process::audio::{OutputChannels, OutputPort, SampleType};
83    ///
84    /// # fn foo(port: OutputPort) {
85    /// let mut port: OutputPort = /* ... */
86    /// # port;
87    ///
88    /// // Decide what to do using by matching against every possible configuration
89    /// match port.channels().unwrap() {
90    ///     SampleType::F32(buf) => { /* Process the 32-bit buffer */ },
91    ///     SampleType::F64(buf) => { /* Process the 64-bit buffer */ },
92    ///     SampleType::Both(buf32, buf64) => { /* We have both buffers available */ }
93    /// }
94    ///
95    /// // If we're only interested in a single buffer type,
96    /// // we can use SampleType's helper methods:
97    /// let channels: OutputChannels<f32> = port.channels().unwrap().into_f32().unwrap();
98    /// # }
99    /// ```
100    #[inline]
101    pub fn channels(
102        &mut self,
103    ) -> Result<SampleType<OutputChannels<'a, f32>, OutputChannels<'a, f64>>, BufferError> {
104        // SAFETY: this type ensures the buffer is valid
105        Ok(unsafe { SampleType::from_raw_buffer_mut(self.inner) }?.map(
106            |data| OutputChannels {
107                data,
108                frames_count: self.frames_count,
109            },
110            |data| OutputChannels {
111                data,
112                frames_count: self.frames_count,
113            },
114        ))
115    }
116
117    /// Returns the number of frames to process in this block.
118    ///
119    /// This will always match the number of samples of every audio channel buffer.
120    #[inline]
121    pub fn frames_count(&self) -> u32 {
122        self.frames_count
123    }
124
125    /// The number of channels in this port.
126    #[inline]
127    pub fn channel_count(&self) -> u32 {
128        self.inner.channel_count
129    }
130
131    /// The latency from the audio interface for this port, in samples.
132    #[inline]
133    pub fn latency(&self) -> u32 {
134        self.inner.latency
135    }
136
137    /// The constant mask for this port.
138    #[inline]
139    pub fn constant_mask(&self) -> ConstantMask {
140        ConstantMask::from_bits(self.inner.constant_mask)
141    }
142
143    /// Sets the constant mask for this port.
144    #[inline]
145    pub fn set_constant_mask(&mut self, new_mask: ConstantMask) {
146        self.inner.constant_mask = new_mask.to_bits()
147    }
148}
149
150/// An [`OutputPort`]'s channels' data buffers, which contains samples of a given type `S`.
151///
152/// The sample type `S` is always going to be either [`f32`] or [`f64`], as returned by
153/// [`OutputPort::channels`].
154pub struct OutputChannels<'a, S> {
155    pub(crate) frames_count: u32,
156    pub(crate) data: &'a mut [*mut S],
157}
158
159impl<S> OutputChannels<'_, S> {
160    /// Returns the number of frames to process in this block.
161    ///
162    /// This will always match the number of samples of every audio channel buffer.
163    #[inline]
164    pub fn frames_count(&self) -> u32 {
165        self.frames_count
166    }
167
168    /// Returns the raw pointer data, as provided by the host.
169    ///
170    /// In CLAP's API, hosts provide a port's audio data as an array of raw pointers, each of which points
171    /// to the start of a sample array of type `S` and of [`frames_count`](Self::frames_count) length.
172    #[inline]
173    pub fn raw_data(&self) -> &[*mut S] {
174        self.data
175    }
176
177    /// The number of channels.
178    #[inline]
179    pub fn channel_count(&self) -> u32 {
180        // This is always constructed from u32, so overflow should not be able to happen
181        #[allow(clippy::cast_possible_truncation)]
182        {
183            self.data.len() as u32
184        }
185    }
186
187    /// Retrieves the sample buffer of the channel at a given index, as a read-only slice.
188    #[inline]
189    pub fn channel(&self, channel_index: u32) -> Option<&[S]> {
190        // SAFETY: this type enforces that the buffer is valid, and has length frames_count.
191        unsafe {
192            self.data.get(channel_index as usize).map(|data| {
193                slice_from_external_parts(*data as *const _, self.frames_count as usize)
194            })
195        }
196    }
197
198    /// Retrieves the sample buffer of the channel at a given index, as a mutable slice.
199    #[inline]
200    pub fn channel_mut(&mut self, channel_index: u32) -> Option<&mut [S]> {
201        // SAFETY: this type enforces that the buffer is valid, has length frames_count, and has
202        // exclusive access.
203        unsafe {
204            self.data.get(channel_index as usize).map(|data| {
205                slice_from_external_parts_mut(*data as *mut _, self.frames_count as usize)
206            })
207        }
208    }
209
210    /// Gets a read-only iterator over all the port's channels' sample buffers.
211    #[inline]
212    pub fn iter(&self) -> InputChannelsIter<'_, S> {
213        InputChannelsIter {
214            data: self.data.iter(),
215            frames_count: self.frames_count,
216        }
217    }
218
219    /// Gets an iterator over all the port's channels' writable sample buffers.
220    #[inline]
221    pub fn iter_mut(&mut self) -> OutputChannelsIter<'_, S> {
222        OutputChannelsIter {
223            data: self.data.as_mut().iter_mut(),
224            frames_count: self.frames_count,
225        }
226    }
227
228    /// Divides the output channels into two at an index.
229    ///
230    /// The first will contain all channels with indices from `[0, mid)` (excluding
231    /// the index `mid` itself) and the second will contain all channels with
232    /// indices from `[mid, channel_count)`.
233    ///
234    /// Unlike [`slice::split_at_mut`], this method does not panic if
235    /// `mid` is larger than `channel_count`.
236    /// The second [`OutputChannels`] will only be empty in this case.
237    #[inline]
238    pub fn split_at_mut(&mut self, mid: u32) -> (OutputChannels<'_, S>, OutputChannels<'_, S>) {
239        let mid = mid as usize;
240        if mid >= self.data.len() {
241            return (
242                OutputChannels {
243                    data: self.data,
244                    frames_count: self.frames_count,
245                },
246                OutputChannels {
247                    data: &mut [],
248                    frames_count: self.frames_count,
249                },
250            );
251        }
252        // PANIC: Checked that mid < len above
253        let (left, right) = self.data.split_at_mut(mid);
254
255        (
256            OutputChannels {
257                data: left,
258                frames_count: self.frames_count,
259            },
260            OutputChannels {
261                data: right,
262                frames_count: self.frames_count,
263            },
264        )
265    }
266}
267impl<'a, T> IntoIterator for &'a OutputChannels<'a, T> {
268    type Item = &'a [T];
269    type IntoIter = InputChannelsIter<'a, T>;
270
271    #[inline]
272    fn into_iter(self) -> Self::IntoIter {
273        self.iter()
274    }
275}
276
277impl<'a, T> IntoIterator for &'a mut OutputChannels<'a, T> {
278    type Item = &'a mut [T];
279    type IntoIter = OutputChannelsIter<'a, T>;
280
281    #[inline]
282    fn into_iter(self) -> Self::IntoIter {
283        self.iter_mut()
284    }
285}
286
287impl<'a, T> IntoIterator for OutputChannels<'a, T> {
288    type Item = &'a mut [T];
289    type IntoIter = OutputChannelsIter<'a, T>;
290
291    #[inline]
292    fn into_iter(self) -> Self::IntoIter {
293        OutputChannelsIter {
294            data: self.data.as_mut().iter_mut(),
295            frames_count: self.frames_count,
296        }
297    }
298}
299
300/// An iterator over all of an [`OutputPort`]'s channels' writable sample buffers.
301pub struct OutputChannelsIter<'a, T> {
302    data: IterMut<'a, *mut T>,
303    frames_count: u32,
304}
305
306impl<'a, T> Iterator for OutputChannelsIter<'a, T> {
307    type Item = &'a mut [T];
308
309    #[inline]
310    fn next(&mut self) -> Option<Self::Item> {
311        // SAFETY: iterator can only get created from an OutputChannels, which guarantees
312        // the buffer is both valid and of length frames_count
313        self.data.next().map(|ptr| unsafe {
314            slice_from_external_parts_mut(*ptr as *mut _, self.frames_count as usize)
315        })
316    }
317
318    #[inline]
319    fn size_hint(&self) -> (usize, Option<usize>) {
320        self.data.size_hint()
321    }
322}
323
324impl<S> ExactSizeIterator for OutputChannelsIter<'_, S> {
325    #[inline]
326    fn len(&self) -> usize {
327        self.data.len()
328    }
329}