dynwave/
utils.rs

1use cpal::{Data, FromSample, Sample, SampleFormat, SizedSample};
2use ringbuf::{traits::Consumer, HeapCons};
3
4// Type alias for the processing function - matches the required callback signature
5type ProcessingFn = Box<dyn FnMut(&mut Data, &cpal::OutputCallbackInfo) + Send + 'static>;
6
7// Function to create the appropriate processing function based on format
8pub fn create_output_processor<T>(
9    format: SampleFormat,
10    mut buffer_consumer: HeapCons<T>,
11) -> ProcessingFn
12where
13    T: Sample + SizedSample + Send + 'static,
14
15    // sadly, cpal uses macro to generate those, and there is no auto way
16    // to use the type system to, even though it seems that it makes sense
17    // to have `T : FromSample<W> where W: SizedSample`?
18    i8: FromSample<T>,
19    i16: FromSample<T>,
20    i32: FromSample<T>,
21    i64: FromSample<T>,
22    u8: FromSample<T>,
23    u16: FromSample<T>,
24    u32: FromSample<T>,
25    u64: FromSample<T>,
26    f32: FromSample<T>,
27    f64: FromSample<T>,
28{
29    match format {
30        SampleFormat::I8 => Box::new(move |data, _| {
31            for sample in data.as_slice_mut::<i8>().expect("Valid format") {
32                *sample = i8::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
33            }
34        }),
35        SampleFormat::I16 => Box::new(move |data, _| {
36            for sample in data.as_slice_mut::<i16>().expect("Valid format") {
37                *sample = i16::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
38            }
39        }),
40        SampleFormat::I32 => Box::new(move |data, _| {
41            for sample in data.as_slice_mut::<i32>().expect("Valid format") {
42                *sample = i32::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
43            }
44        }),
45        SampleFormat::I64 => Box::new(move |data, _| {
46            for sample in data.as_slice_mut::<i64>().expect("Valid format") {
47                *sample = i64::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
48            }
49        }),
50        SampleFormat::U8 => Box::new(move |data, _| {
51            for sample in data.as_slice_mut::<u8>().expect("Valid format") {
52                *sample = u8::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
53            }
54        }),
55        SampleFormat::U16 => Box::new(move |data, _| {
56            for sample in data.as_slice_mut::<u16>().expect("Valid format") {
57                *sample = u16::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
58            }
59        }),
60        SampleFormat::U32 => Box::new(move |data, _| {
61            for sample in data.as_slice_mut::<u32>().expect("Valid format") {
62                *sample = u32::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
63            }
64        }),
65        SampleFormat::U64 => Box::new(move |data, _| {
66            for sample in data.as_slice_mut::<u64>().expect("Valid format") {
67                *sample = u64::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
68            }
69        }),
70        SampleFormat::F32 => Box::new(move |data, _| {
71            for sample in data.as_slice_mut::<f32>().expect("Valid format") {
72                *sample = f32::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
73            }
74        }),
75        SampleFormat::F64 => Box::new(move |data, _| {
76            for sample in data.as_slice_mut::<f64>().expect("Valid format") {
77                *sample = f64::from_sample(buffer_consumer.try_pop().unwrap_or(T::EQUILIBRIUM));
78            }
79        }),
80        e => panic!("Format {e:?} isn't supported"),
81    }
82}