1use crate::{Sample, I24, U24};
2use byte_slice_cast::AsByteSlice;
3use ezk::ValueRange;
4use std::alloc::Layout;
5use std::any::TypeId;
6use std::collections::VecDeque;
7use std::fmt;
8use std::mem::take;
9
10impl Format {
11 #[must_use]
12 pub fn is_float(self) -> bool {
13 matches!(self, Self::F32 | Self::F64)
14 }
15}
16
17macro_rules! sample_formats {
18 ($($variant:ident: $T:ident, $bits:expr;)+) => {
19 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20 pub enum Format {
21 $($variant,)+
22 }
23
24 impl Format {
25 #[must_use]
26 pub fn all() -> ValueRange<Self> {
27 ValueRange::AnyOf(vec![
28 $(ValueRange::Value(Self::$variant),)+
29 ])
30 }
31
32 #[must_use]
33 pub const fn bits_per_sample(&self) -> usize {
34 match self {
35 $(Self::$variant => $bits,)+
36 }
37 }
38
39 #[must_use]
40 pub const fn bytes_per_sample(&self) -> usize {
41 self.bits_per_sample().div_ceil(8)
42 }
43 }
44
45 #[derive(Clone, PartialEq)]
46 pub enum Samples {
47 $($variant (Vec<$T>),)+
48 }
49
50 impl Samples {
51 #[must_use]
52 pub const fn empty(format: Format) -> Self {
53 match format {
54 $(Format::$variant => Self::$variant(Vec::new()),)+
55 }
56 }
57
58 #[must_use]
60 pub fn equilibrium(format: Format, len: usize) -> Self {
61 match format {
62 $(Format::$variant => Self::$variant(vec![<$T as Sample>::equilibrium(); len]),)+
63 }
64 }
65
66 #[must_use]
67 pub fn with_capacity(format: Format, capacity: usize) -> Self {
68 match format {
69 $(Format::$variant => Self::$variant(Vec::with_capacity(capacity)),)+
70 }
71 }
72
73 #[must_use]
75 pub fn len(&self) -> usize {
76 match self {
77 $(Self::$variant(vec) => vec.len(),)+
78 }
79 }
80
81 #[must_use]
82 pub fn is_empty(&self) -> bool {
83 self.len() == 0
84 }
85
86 #[must_use]
88 pub fn format(&self) -> Format {
89 match self {
90 $(Self::$variant(..) => Format::$variant,)+
91 }
92 }
93
94 #[must_use]
95 pub fn as_bytes(&self) -> &[u8] {
96 match self {
97 $(Self::$variant(v) => v.as_byte_slice(),)*
98 }
99 }
100
101 #[must_use]
102 pub fn from_ne_bytes(format: Format, bytes: &[u8]) -> Self {
103 if cfg!(target_endian = "big") {
104 Self::from_be_bytes(format, bytes)
105 } else {
106 Self::from_le_bytes(format, bytes)
107 }
108 }
109
110 #[must_use]
111 pub fn from_be_bytes(format: Format, bytes: &[u8]) -> Self {
112 let bytes_per_sample = format.bytes_per_sample();
113 assert_eq!(bytes.len() % bytes_per_sample, 0);
114
115 match format {
116 $(Format::$variant => {
117 Self::$variant(
118 bytes
119 .chunks_exact(bytes_per_sample)
120 .map(|chunk| {
121 $T::from_be_bytes(chunk.try_into().expect("from_be_bytes must accept size_of::<Self> amount of bytes"))
122 })
123 .collect()
124 )
125 },)+
126 }
127 }
128
129 #[must_use]
130 pub fn from_le_bytes(format: Format, bytes: &[u8]) -> Self {
131 let bytes_per_sample = format.bytes_per_sample();
132 assert_eq!(bytes.len() % bytes_per_sample, 0);
133
134 match format {
135 $(Format::$variant => {
136 Self::$variant(
137 bytes
138 .chunks_exact(bytes_per_sample)
139 .map(|chunk| {
140 $T::from_le_bytes(chunk.try_into().expect("from_le_bytes must accept size_of::<Self> amount of bytes"))
141 })
142 .collect()
143 )
144 },)+
145 }
146 }
147
148 #[must_use]
150 pub fn into_samples<S: Sample>(self) -> Vec<S> {
151 match self {
152 $(
153 Self::$variant(mut v) => {
154 if TypeId::of::<$T>() == TypeId::of::<S>() {
155 unsafe { std::mem::transmute::<Vec<$T>, Vec<S>>(v) }
157 } else if Layout::new::<$T>() == Layout::new::<S>() {
158 unsafe { convert_with_dst_and_src_type_inplace(&mut v) }
160 } else {
161 v.into_iter().map(|s| s.to_sample::<S>()).collect()
162 }
163 },
164 )*
165 }
166 }
167
168 #[must_use]
170 pub fn to_samples<S: Sample>(&self) -> Vec<S> {
171 match self {
172 $(
173 Self::$variant(v) => v.iter().map(|s| s.to_sample::<S>()).collect(),
174 )*
175 }
176 }
177 }
178
179 impl fmt::Debug for Samples {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 match self {
182 $(Self::$variant(v) => write!(f, "Samples(format = {}, len = {})", stringify!($variant), v.len()),)*
183 }
184 }
185 }
186
187 $(
188 impl From<Vec<$T>> for Samples {
189 fn from(vec: Vec<$T>) -> Self {
190 Self::$variant(vec.into())
191 }
192 }
193 )+
194
195 pub enum SamplesQueue {
196 $($variant (VecDeque<$T>),)+
197 }
198
199 impl SamplesQueue {
200 #[must_use]
201 pub fn empty(format: Format) -> Self {
202 match format {
203 $(Format::$variant => Self::$variant(VecDeque::new()),)+
204 }
205 }
206
207 #[must_use]
208 pub fn len(&self) -> usize {
209 match self {
210 $(Self::$variant(queue) => queue.len(),)+
211 }
212 }
213
214 #[must_use]
215 pub fn is_empty(&self) -> bool {
216 self.len() == 0
217 }
218
219 pub fn extend(&mut self, samples: &Samples) {
220 match (self, samples) {
221 $(
222 (Self::$variant(queue), Samples::$variant(vec)) => { queue.extend(vec.iter().copied()) },
223 )+
224 _ => panic!("Tried to extend SampleQueue with different sample format"),
225 }
226 }
227
228 pub fn pop_exact(&mut self, n: usize) -> Option<Samples> {
229 match self {
230 $(Self::$variant(queue) => {
231 if queue.len() < n {
232 return None;
233 }
234
235 Some(Samples::$variant(queue.drain(..n).collect()))
236 },)+
237 }
238 }
239 }
240
241 impl fmt::Debug for SamplesQueue {
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 match self {
244 $(Self::$variant(v) => write!(f, "SamplesQueue(format = {}, len = {})", stringify!($variant), v.len()),)*
245 }
246 }
247 }
248 }
249}
250
251sample_formats! {
252 F64: f64, 64;
253 F32: f32, 32;
254
255 I32: i32, 32;
256 U32: u32, 32;
257
258 I24: I24, 24;
259 U24: U24, 24;
260
261 I16: i16, 16;
262 U16: u16, 16;
263
264 I8: i8, 8;
265 U8: u8, 8;
266}
267
268#[macro_export]
288macro_rules! match_format {
289 ($format:expr, $($input:tt)*) => {
290 match $format {
291 $crate::Format::F64 => { $crate::substitute!($crate::__private_macro_exports::f64 => $($input)*) }
292 $crate::Format::F32 => { $crate::substitute!($crate::__private_macro_exports::f32 => $($input)*) }
293 $crate::Format::I32 => { $crate::substitute!($crate::__private_macro_exports::i32 => $($input)*) }
294 $crate::Format::U32 => { $crate::substitute!($crate::__private_macro_exports::u32 => $($input)*) }
295 $crate::Format::I24 => { $crate::substitute!($crate::__private_macro_exports::I24 => $($input)*) }
296 $crate::Format::U24 => { $crate::substitute!($crate::__private_macro_exports::U24 => $($input)*) }
297 $crate::Format::I16 => { $crate::substitute!($crate::__private_macro_exports::i16 => $($input)*) }
298 $crate::Format::U16 => { $crate::substitute!($crate::__private_macro_exports::u16 => $($input)*) }
299 $crate::Format::I8 => { $crate::substitute!($crate::__private_macro_exports::i8 => $($input)*) }
300 $crate::Format::U8 => { $crate::substitute!($crate::__private_macro_exports::u8 => $($input)*) }
301 }
302 };
303}
304
305#[macro_export]
356macro_rules! match_samples {
357 (($($samples:expr),*) => ($($pat:pat),*) => $($input:tt)*) => {
358 match ($($samples,)*) {
359 ($($crate::Samples::F64($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::f64 => $($input)*) }
360 ($($crate::Samples::F32($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::f32 => $($input)*) }
361 ($($crate::Samples::I32($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::i32 => $($input)*) }
362 ($($crate::Samples::U32($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::u32 => $($input)*) }
363 ($($crate::Samples::I24($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::I24 => $($input)*) }
364 ($($crate::Samples::U24($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::U24 => $($input)*) }
365 ($($crate::Samples::I16($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::i16 => $($input)*) }
366 ($($crate::Samples::U16($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::u16 => $($input)*) }
367 ($($crate::Samples::I8($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::i8 => $($input)*) }
368 ($($crate::Samples::U8($pat),)*) => { $crate::substitute!($crate::__private_macro_exports::u8 => $($input)*) }
369
370 #[allow(unreachable_patterns)] _ => panic!("Tried to match multiple samples with different sample types")
371 }
372 };
373}
374
375#[macro_export]
385#[doc(hidden)]
386macro_rules! substitute {
387 ($i1:ty => $($input:tt)*) => {
388 $crate::substitute!(@inner $i1 => [] [$($input)*])
389 };
390 (@inner
391 $i1:ty =>
392 [$($processed:tt)*]
393 [#S $($input:tt)*]
394 ) => {
395 $crate::substitute!(@inner $i1 =>
396 [$($processed)* $i1]
397 [$($input)*]
398 )
399 };
400 (@inner
401 $i1:ty =>
402 [$($processed:tt)*]
403 [{ $($block_input:tt)* } $($input:tt)*]
404 ) => {
405 $crate::substitute!(@inner $i1 =>
406 [$($processed)* { $crate::substitute! { $i1 => $($block_input)* } }]
407 [$($input)*]
408 )
409 };
410 (@inner
411 $i1:ty =>
412 [$($processed:tt)*]
413 [$token:tt $($input:tt)*]
414 ) => {
415 $crate::substitute!(@inner $i1 =>
416 [$($processed)* $token]
417 [$($input)*]
418 )
419 };
420 (@inner
421 $i1:ty =>
422 [$($processed:tt)*]
423 []
424 ) => {
425 $($processed)*
426 };
427}
428
429unsafe fn convert_with_dst_and_src_type_inplace<Src, Dst>(src: &mut Vec<Src>) -> Vec<Dst>
431where
432 Src: Sample,
433 Dst: Sample,
434{
435 let src = take(src);
436
437 let (ptr, len, cap) = vec_into_raw_parts(src);
438
439 for offset in 0..len {
440 let ptr = ptr.add(offset);
441 let src = ptr.read();
442 let ptr = ptr.cast::<Dst>();
443 ptr.write(src.to_sample());
444 }
445
446 Vec::from_raw_parts(ptr.cast::<Dst>(), len, cap)
447}
448
449fn vec_into_raw_parts<T>(vec: Vec<T>) -> (*mut T, usize, usize) {
450 let mut vec = std::mem::ManuallyDrop::new(vec);
451 (vec.as_mut_ptr(), vec.len(), vec.capacity())
452}