screencapturekit/cm/
audio.rs

1//! Audio buffer types
2
3use std::fmt;
4
5pub struct AudioBuffer {
6    pub number_channels: u32,
7    pub data_bytes_size: u32,
8    data_ptr: *mut std::ffi::c_void,
9}
10
11impl PartialEq for AudioBuffer {
12    fn eq(&self, other: &Self) -> bool {
13        self.number_channels == other.number_channels
14            && self.data_bytes_size == other.data_bytes_size
15            && self.data_ptr == other.data_ptr
16    }
17}
18
19impl Eq for AudioBuffer {}
20
21impl std::hash::Hash for AudioBuffer {
22    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
23        self.number_channels.hash(state);
24        self.data_bytes_size.hash(state);
25        self.data_ptr.hash(state);
26    }
27}
28
29impl fmt::Display for AudioBuffer {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        write!(
32            f,
33            "AudioBuffer({} channels, {} bytes)",
34            self.number_channels, self.data_bytes_size
35        )
36    }
37}
38
39impl AudioBuffer {
40    pub fn data(&self) -> &[u8] {
41        if self.data_ptr.is_null() || self.data_bytes_size == 0 {
42            &[]
43        } else {
44            unsafe {
45                std::slice::from_raw_parts(
46                    self.data_ptr as *const u8,
47                    self.data_bytes_size as usize,
48                )
49            }
50        }
51    }
52
53    pub fn data_mut(&mut self) -> &mut [u8] {
54        if self.data_ptr.is_null() || self.data_bytes_size == 0 {
55            &mut []
56        } else {
57            unsafe {
58                std::slice::from_raw_parts_mut(
59                    self.data_ptr.cast::<u8>(),
60                    self.data_bytes_size as usize,
61                )
62            }
63        }
64    }
65
66    pub fn get_data_byte_size(&self) -> usize {
67        self.data_bytes_size as usize
68    }
69}
70
71/// Reference to an audio buffer with convenience methods
72pub struct AudioBufferRef<'a> {
73    buffer: &'a AudioBuffer,
74}
75
76impl AudioBufferRef<'_> {
77    pub fn get_data_byte_size(&self) -> usize {
78        self.buffer.get_data_byte_size()
79    }
80
81    pub fn data(&self) -> &[u8] {
82        self.buffer.data()
83    }
84}
85
86/// List of audio buffers from an audio sample
87#[repr(C)]
88#[derive(Debug)]
89pub struct AudioBufferListRaw {
90    pub(crate) num_buffers: u32,
91    pub(crate) buffers_ptr: *mut AudioBuffer,
92    pub(crate) buffers_len: usize,
93}
94
95pub struct AudioBufferList {
96    pub(crate) inner: AudioBufferListRaw,
97}
98
99impl AudioBufferList {
100    pub fn num_buffers(&self) -> usize {
101        self.inner.num_buffers as usize
102    }
103
104    pub fn get_number_buffers(&self) -> usize {
105        self.num_buffers()
106    }
107
108    pub fn get(&self, index: usize) -> Option<&AudioBuffer> {
109        if index >= self.num_buffers() {
110            None
111        } else {
112            unsafe { Some(&*self.inner.buffers_ptr.add(index)) }
113        }
114    }
115
116    pub fn get_buffer(&self, index: usize) -> Option<AudioBufferRef<'_>> {
117        self.get(index).map(|buffer| AudioBufferRef { buffer })
118    }
119
120    pub fn get_mut(&mut self, index: usize) -> Option<&mut AudioBuffer> {
121        if index >= self.num_buffers() {
122            None
123        } else {
124            unsafe { Some(&mut *self.inner.buffers_ptr.add(index)) }
125        }
126    }
127
128    pub fn iter(&self) -> AudioBufferListIter<'_> {
129        AudioBufferListIter {
130            list: self,
131            index: 0,
132        }
133    }
134}
135
136impl Drop for AudioBufferList {
137    fn drop(&mut self) {
138        if !self.inner.buffers_ptr.is_null() {
139            unsafe {
140                Vec::from_raw_parts(
141                    self.inner.buffers_ptr,
142                    self.inner.buffers_len,
143                    self.inner.buffers_len,
144                );
145            }
146        }
147    }
148}
149
150impl<'a> IntoIterator for &'a AudioBufferList {
151    type Item = &'a AudioBuffer;
152    type IntoIter = AudioBufferListIter<'a>;
153
154    fn into_iter(self) -> Self::IntoIter {
155        self.iter()
156    }
157}
158
159impl fmt::Display for AudioBufferList {
160    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161        write!(f, "AudioBufferList({} buffers)", self.num_buffers())
162    }
163}
164
165pub struct AudioBufferListIter<'a> {
166    list: &'a AudioBufferList,
167    index: usize,
168}
169
170impl<'a> Iterator for AudioBufferListIter<'a> {
171    type Item = &'a AudioBuffer;
172
173    fn next(&mut self) -> Option<Self::Item> {
174        if self.index < self.list.num_buffers() {
175            let buffer = self.list.get(self.index);
176            self.index += 1;
177            buffer
178        } else {
179            None
180        }
181    }
182}