1use crate::math::FP64;
2
3pub mod audio_backends;
4pub mod interval;
5pub mod mixer;
6pub mod pcm_util;
7
8pub use interval::Interval;
10pub use pcm_util::PCMSlice;
11
12pub type DeviceCB<State> = fn(&mut State, &mut [f32]);
14
15pub use audio_backends::*;
17
18use self::mixer::SampleTime;
19pub trait GenericAudioSpecs {
21 fn sample_rate(&self) -> Option<u32>;
22 fn bits_per_sample(&self) -> Option<u32>;
23 fn channels(&self) -> Option<u32>;
24}
25
26#[derive(Copy, Clone, Default)]
29pub struct DesiredSpecs {
30 pub sample_rate: Option<u32>,
31 pub channels: Option<u32>,
32 pub buffer_size: Option<u32>,
34}
35
36#[derive(Copy, Clone)]
37pub struct ConcreteSpecs {
38 pub sample_rate: u32,
39 pub channels: usize,
40 pub buffer_size: usize,
42}
43
44impl DesiredSpecs {
45 pub fn make_concrete(&self) -> ConcreteSpecs {
47 ConcreteSpecs {
48 sample_rate: self.sample_rate.unwrap_or(48000),
49 channels: self.channels.unwrap_or(2) as usize,
50 buffer_size: self.buffer_size.unwrap_or(1024) as usize,
51 }
52 }
53}
54
55#[derive(Default)]
60pub struct AudioDeviceCore<Callback, State> {
61 cb: Option<Callback>,
62 state: Option<State>,
63 desired_specs: DesiredSpecs,
64}
65
66impl<Callback, State> AudioDeviceCore<Callback, State>
67where
68 Callback: FnMut(&mut State, &mut [f32]) + Copy + 'static,
69 State: 'static,
70{
71 pub fn new() -> Self {
72 Self {
73 cb: None,
74 state: None,
75 desired_specs: DesiredSpecs {
76 sample_rate: None,
77 channels: None,
78 buffer_size: None,
79 },
80 }
81 }
82 pub fn with_callback(mut self, cb: Callback) -> Self {
85 self.cb = Some(cb);
86 self
87 }
88
89 pub fn with_state(mut self, state: State) -> Self {
90 self.state = Some(state);
91 self
92 }
93
94 pub fn with_specs(mut self, specs: DesiredSpecs) -> Self {
95 self.desired_specs = specs;
96 self
97 }
98
99 pub fn callback(&self) -> Callback {
100 self.cb.unwrap()
101 }
102}
103
104pub fn calculate_samples_needed_per_channel_st(frequency: u32, dt: FP64) -> SampleTime {
106 const MILLISECONDS_IN_ONE_SEC: i32 = 1000;
107 let sample_count = (FP64::from(frequency) * dt) / MILLISECONDS_IN_ONE_SEC;
108 SampleTime::new()
109 .with_sample_rate(frequency)
110 .with_sample_count(sample_count.as_i64() as u64)
111}
112
113pub fn calculate_samples_needed_per_channel_fp(frequency: u32, dt: FP64) -> FP64 {
115 const MILLISECONDS_IN_ONE_SEC: i32 = 1000;
116 (FP64::from(frequency) * dt) / MILLISECONDS_IN_ONE_SEC
117}
118
119pub fn calculate_elapsed_time_in_ms_fp(frequency: u32, num_samples: usize) -> FP64 {
123 FP64::from(num_samples as u64 * 1000) / FP64::from(frequency)
124}