nice_plug_core/buffer/
samples.rs1use std::marker::PhantomData;
4
5#[cfg(feature = "simd")]
6use std::simd::Simd;
7
8pub struct SamplesIter<'slice, 'sample: 'slice> {
11 pub(super) buffers: *mut [&'sample mut [f32]],
13 pub(super) current_sample: usize,
14 pub(super) samples_end: usize,
18 pub(super) _marker: PhantomData<&'slice mut [&'sample mut [f32]]>,
19}
20
21pub struct ChannelSamples<'slice, 'sample: 'slice> {
26 pub(self) buffers: *mut [&'sample mut [f32]],
28 pub(self) current_sample: usize,
29 pub(self) _marker: PhantomData<&'slice mut [&'sample mut [f32]]>,
30}
31
32pub struct ChannelSamplesIter<'slice, 'sample: 'slice> {
34 pub(self) buffers: *mut [&'sample mut [f32]],
36 pub(self) current_sample: usize,
37 pub(self) current_channel: usize,
38 pub(self) _marker: PhantomData<&'slice mut [&'sample mut [f32]]>,
39}
40
41impl<'slice, 'sample> Iterator for SamplesIter<'slice, 'sample> {
42 type Item = ChannelSamples<'slice, 'sample>;
43
44 #[inline]
45 fn next(&mut self) -> Option<Self::Item> {
46 if self.current_sample < self.samples_end {
48 let channels = ChannelSamples {
49 buffers: self.buffers,
50 current_sample: self.current_sample,
51 _marker: self._marker,
52 };
53
54 self.current_sample += 1;
55
56 Some(channels)
57 } else {
58 None
59 }
60 }
61
62 #[inline]
63 fn size_hint(&self) -> (usize, Option<usize>) {
64 let remaining = self.samples_end - self.current_sample;
65
66 (remaining, Some(remaining))
67 }
68}
69
70impl<'slice, 'sample> IntoIterator for ChannelSamples<'slice, 'sample> {
71 type Item = &'sample mut f32;
72 type IntoIter = ChannelSamplesIter<'slice, 'sample>;
73
74 #[inline]
75 fn into_iter(self) -> Self::IntoIter {
76 ChannelSamplesIter {
77 buffers: self.buffers,
78 current_sample: self.current_sample,
79 current_channel: 0,
80 _marker: self._marker,
81 }
82 }
83}
84
85impl<'slice, 'sample> Iterator for ChannelSamplesIter<'slice, 'sample> {
86 type Item = &'sample mut f32;
87
88 #[inline]
89 fn next(&mut self) -> Option<Self::Item> {
90 if self.current_channel < unsafe { (&(*self.buffers)).len() } {
91 let sample = unsafe {
95 (&mut (*self.buffers))
96 .get_unchecked_mut(self.current_channel)
97 .get_unchecked_mut(self.current_sample)
98 };
99
100 self.current_channel += 1;
101
102 Some(sample)
103 } else {
104 None
105 }
106 }
107
108 #[inline]
109 fn size_hint(&self) -> (usize, Option<usize>) {
110 let remaining = unsafe { (&(*self.buffers)).len() } - self.current_channel;
111
112 (remaining, Some(remaining))
113 }
114}
115
116impl ExactSizeIterator for SamplesIter<'_, '_> {}
117impl ExactSizeIterator for ChannelSamplesIter<'_, '_> {}
118
119impl<'slice, 'sample> ChannelSamples<'slice, 'sample> {
120 #[allow(clippy::len_without_is_empty)]
122 #[inline]
123 pub fn len(&self) -> usize {
124 unsafe { (&(*self.buffers)).len() }
125 }
126
127 #[inline]
131 pub fn iter_mut(&mut self) -> ChannelSamplesIter<'slice, 'sample> {
132 ChannelSamplesIter {
133 buffers: self.buffers,
134 current_sample: self.current_sample,
135 current_channel: 0,
136 _marker: self._marker,
137 }
138 }
139
140 #[inline]
143 pub fn get_mut(&mut self, channel_index: usize) -> Option<&mut f32> {
144 unsafe {
146 Some(
147 (&mut (*self.buffers))
148 .get_mut(channel_index)?
149 .get_unchecked_mut(self.current_sample),
150 )
151 }
152 }
153
154 #[inline]
160 pub unsafe fn get_unchecked_mut(&mut self, channel_index: usize) -> &mut f32 {
161 unsafe {
162 (&mut (*self.buffers))
163 .get_unchecked_mut(channel_index)
164 .get_unchecked_mut(self.current_sample)
165 }
166 }
167
168 #[cfg(feature = "simd")]
172 #[inline]
173 pub fn to_simd<const LANES: usize>(&self) -> Simd<f32, LANES> {
174 let used_lanes = self.len().max(LANES);
175 let mut values = [0.0; LANES];
176 for (channel_idx, value) in values.iter_mut().enumerate().take(used_lanes) {
177 *value = unsafe {
178 *(&(*self.buffers))
179 .get_unchecked(channel_idx)
180 .get_unchecked(self.current_sample)
181 };
182 }
183
184 Simd::from_array(values)
185 }
186
187 #[cfg(feature = "simd")]
194 #[inline]
195 pub unsafe fn to_simd_unchecked<const LANES: usize>(&self) -> Simd<f32, LANES> {
196 let mut values = [0.0; LANES];
197 for (channel_idx, value) in values.iter_mut().enumerate() {
198 *value = unsafe {
199 *(&(*self.buffers))
200 .get_unchecked(channel_idx)
201 .get_unchecked(self.current_sample)
202 };
203 }
204
205 Simd::from_array(values)
206 }
207
208 #[cfg(feature = "simd")]
211 #[allow(clippy::wrong_self_convention)]
212 #[inline]
213 pub fn from_simd<const LANES: usize>(&mut self, vector: Simd<f32, LANES>) {
214 let used_lanes = self.len().max(LANES);
215 let values = vector.to_array();
216 for (channel_idx, value) in values.into_iter().enumerate().take(used_lanes) {
217 *unsafe {
218 (&mut (*self.buffers))
219 .get_unchecked_mut(channel_idx)
220 .get_unchecked_mut(self.current_sample)
221 } = value;
222 }
223 }
224
225 #[cfg(feature = "simd")]
232 #[allow(clippy::wrong_self_convention)]
233 #[inline]
234 pub unsafe fn from_simd_unchecked<const LANES: usize>(&mut self, vector: Simd<f32, LANES>) {
235 let values = vector.to_array();
236 for (channel_idx, value) in values.into_iter().enumerate() {
237 unsafe {
238 *(&mut (*self.buffers))
239 .get_unchecked_mut(channel_idx)
240 .get_unchecked_mut(self.current_sample) = value;
241 }
242 }
243 }
244}