clap_clap/
audio_buffer.rs

1use std::ptr::{NonNull, slice_from_raw_parts, slice_from_raw_parts_mut};
2
3use crate::{ffi::clap_audio_buffer, prelude::Process};
4
5/// Shared audio buffer.
6pub struct AudioBuffer<'a> {
7    process: &'a Process,
8    clap_audio_buffer: *const clap_audio_buffer,
9}
10
11impl<'a> AudioBuffer<'a> {
12    /// # Safety
13    ///
14    /// `clap_audio_buffer` must be non-null and must belong to Process.
15    pub const unsafe fn new_unchecked(
16        process: &'a Process,
17        clap_audio_buffer: *const clap_audio_buffer,
18    ) -> Self {
19        debug_assert!(!clap_audio_buffer.is_null());
20        Self {
21            process,
22            clap_audio_buffer,
23        }
24    }
25
26    const fn clap_audio_buffer(&self) -> &clap_audio_buffer {
27        // SAFETY: By construction, audio_buffer can be only obtained from a shared
28        // reference to Process.
29        unsafe { self.clap_audio_buffer.as_ref().unwrap() }
30    }
31
32    /// # Safety
33    ///
34    /// 1. `channel` must be less than `self.channel_count()`,
35    /// 2. `process.frames_count()` must fit into `usize` (cast).
36    pub const unsafe fn data32_unchecked(&self, channel: u32) -> &[f32] {
37        debug_assert!(channel < self.channel_count());
38        // SAFETY: The caller guarantees this dereferencing is safe.
39        let chan = unsafe { *self.clap_audio_buffer().data32.add(channel as usize) };
40
41        debug_assert!((self.process.frames_count() as u64) < usize::MAX as u64);
42        // SAFETY: The CLAP host guarantees that the channel is at
43        // least process.frames_count() long.
44        unsafe { &*slice_from_raw_parts(chan, self.process.frames_count() as usize) }
45    }
46
47    /// # Panic
48    ///
49    /// This function will panic if `channel` is larger or equal to
50    /// `self.channel.count()`.
51    pub const fn data32(&self, channel: u32) -> &[f32] {
52        assert!(
53            channel < self.channel_count(),
54            "channel number must be less that the number of available channels"
55        );
56
57        // SAFETY: we just checked if `channel < self.channel_count()`
58        unsafe { self.data32_unchecked(channel) }
59    }
60
61    /// # Safety
62    ///
63    /// 1. `channel` must be less than `self.channel_count()`,
64    /// 2. `process.frames_count()` must fit into `usize` (cast).
65    pub const unsafe fn data64_unchecked(&self, channel: u32) -> &[f64] {
66        debug_assert!(channel < self.channel_count());
67        // SAFETY: The caller guarantees this dereferencing is safe.
68        let chan = unsafe { *self.clap_audio_buffer().data64.add(channel as usize) };
69
70        debug_assert!((self.process.frames_count() as u64) < usize::MAX as u64);
71        // SAFETY: The CLAP host guarantees that the channel is at
72        // least process.frames_count() long.
73        unsafe { &*slice_from_raw_parts(chan, self.process.frames_count() as usize) }
74    }
75
76    /// # Panic
77    ///
78    /// This function will panic if `channel` is larger or equal to
79    /// `self.channel.count()`.
80    pub const fn data64(&self, channel: u32) -> &[f64] {
81        assert!(
82            channel < self.channel_count(),
83            "channel number must be less that the number of available channels"
84        );
85
86        // SAFETY: we just checked if `channel < self.channel_count()`
87        unsafe { self.data64_unchecked(channel) }
88    }
89
90    pub const fn channel_count(&self) -> u32 {
91        self.clap_audio_buffer().channel_count
92    }
93
94    pub const fn latency(&self) -> u32 {
95        self.clap_audio_buffer().latency
96    }
97
98    pub const fn constant_mask(&self) -> u64 {
99        self.clap_audio_buffer().constant_mask
100    }
101}
102
103/// Writable audio buffer.
104pub struct AudioBufferMut<'a> {
105    process: &'a mut Process,
106    clap_audio_buffer: NonNull<clap_audio_buffer>,
107}
108
109impl<'a> AudioBufferMut<'a> {
110    /// # Safety
111    ///
112    /// `clap_audio_buffer` must be a writable buffer that belongs to Process.
113    pub const unsafe fn new_unchecked(
114        process: &'a mut Process,
115        clap_audio_buffer: NonNull<clap_audio_buffer>,
116    ) -> Self {
117        Self {
118            process,
119            clap_audio_buffer,
120        }
121    }
122
123    const fn clap_audio_buffer(&self) -> &clap_audio_buffer {
124        // SAFETY: The constructor guarantees that we have exclusive access to the audio
125        // buffer. We know that the buffer remains constant for the lifetime of
126        // self, so the aliasing is safe.
127        unsafe { self.clap_audio_buffer.as_ref() }
128    }
129
130    const fn clap_audio_buffer_mut(&mut self) -> &mut clap_audio_buffer {
131        // SAFETY: The constructor guarantees that we have exclusive access to the audio
132        // buffer.
133        unsafe { self.clap_audio_buffer.as_mut() }
134    }
135
136    /// # Safety
137    ///
138    /// 1. The number of channels  must be less than `self.channel_count()`
139    /// 2. `process.frames_count()` must fit into `usize` (cast)
140    const unsafe fn data32_unchecked(&mut self, channel: u32) -> &mut [f32] {
141        debug_assert!(channel < self.channel_count());
142        // SAFETY: The caller guarantees this dereferencing is safe.
143        let chan = unsafe { *self.clap_audio_buffer_mut().data32.add(channel as usize) };
144
145        debug_assert!((self.process.frames_count() as u64) < usize::MAX as u64);
146        // SAFETY: The CLAP host guarantees that the channel is at
147        // least process.frames_count() long.
148        unsafe { &mut *slice_from_raw_parts_mut(chan, self.process.frames_count() as usize) }
149    }
150
151    /// # Panic
152    ///
153    /// This function will panic if `channel` is greater or equal to
154    /// `self.channel.count()`.
155    pub const fn data32(&mut self, channel: u32) -> &mut [f32] {
156        assert!(
157            channel < self.channel_count(),
158            "channel number must be less that the number of available channels"
159        );
160
161        // SAFETY: We just checked if `n < channel_count()`
162        unsafe { self.data32_unchecked(channel) }
163    }
164
165    /// # Safety
166    ///
167    /// 1. The number of channels  must be less than `self.channel_count()`
168    /// 2. `process.frames_count()` must fit into `usize` (cast)
169    const unsafe fn data64_unchecked(&mut self, channel: u32) -> &mut [f64] {
170        debug_assert!(channel < self.channel_count());
171        // SAFETY: The caller guarantees this dereferencing is safe.
172        let chan = unsafe { *self.clap_audio_buffer_mut().data64.add(channel as usize) };
173
174        debug_assert!((self.process.frames_count() as u64) < usize::MAX as u64);
175        // SAFETY: The CLAP host guarantees that the channel is at
176        // least process.frames_count() long.
177        unsafe { &mut *slice_from_raw_parts_mut(chan, self.process.frames_count() as usize) }
178    }
179
180    /// # Panic
181    ///
182    /// This function will panic if `channel` is greater or equal to
183    /// `self.channel.count()`.
184    pub const fn data64(&mut self, channel: u32) -> &mut [f64] {
185        assert!(
186            channel < self.channel_count(),
187            "channel number must be less that the number of available channels"
188        );
189
190        // SAFETY: We just checked if `n < channel_count()`
191        unsafe { self.data64_unchecked(channel) }
192    }
193
194    pub const fn channel_count(&self) -> u32 {
195        self.clap_audio_buffer().channel_count
196    }
197
198    pub const fn latency(&self) -> u32 {
199        self.clap_audio_buffer().latency
200    }
201
202    pub const fn constant_mask(&self) -> u64 {
203        self.clap_audio_buffer().constant_mask
204    }
205}