firewheel_graph/backend.rs
1use bevy_platform::prelude::{String, Vec};
2use core::error::Error;
3use core::time::Duration;
4
5use firewheel_core::{node::StreamStatus, StreamInfo};
6
7use crate::processor::FirewheelProcessor;
8
9/// A trait describing an audio backend.
10///
11/// When an instance is dropped, then it must automatically stop its
12/// corresponding audio stream.
13///
14/// All methods in this trait are only ever invoked from the main
15/// thread (the thread where the [`crate::context::FirewheelCtx`]
16/// lives).
17pub trait AudioBackend: Sized {
18 /// The type used to retrieve the list of available audio devices on
19 /// the system and their available ocnfigurations.
20 type Enumerator;
21 /// The configuration of the audio stream.
22 type Config: Default;
23 /// An error when starting a new audio stream.
24 type StartStreamError: Error;
25 /// An error that has caused the audio stream to stop.
26 type StreamError: Error;
27 /// A type describing an instant in time.
28 type Instant: Send + Clone;
29
30 /// Get a struct used to retrieve the list of available audio devices
31 /// on the system and their available ocnfigurations.
32 fn enumerator() -> Self::Enumerator;
33
34 /// Get a list of available input audio devices (for the default API).
35 ///
36 /// The first item in the list is the default device.
37 fn input_devices_simple(&mut self) -> Vec<DeviceInfoSimple> {
38 Vec::new()
39 }
40
41 /// Get a list of available output audio devices (for the default API).
42 ///
43 /// The first item in the list is the default device.
44 fn output_devices_simple(&mut self) -> Vec<DeviceInfoSimple> {
45 Vec::new()
46 }
47
48 /// Convert the easy-to-use, backend-agnostic audio stream configuration
49 /// into the corresponding backend-specific configuration.
50 fn convert_simple_config(&mut self, config: &SimpleStreamConfig) -> Self::Config {
51 let _ = config;
52 Self::Config::default()
53 }
54
55 /// Start the audio stream with the given configuration, and return
56 /// a handle for the audio stream.
57 fn start_stream(config: Self::Config) -> Result<(Self, StreamInfo), Self::StartStreamError>;
58
59 /// Send the given processor to the audio thread for processing.
60 fn set_processor(&mut self, processor: FirewheelProcessor<Self>);
61
62 /// Poll the status of the running audio stream. Return an error if the
63 /// audio stream has stopped for any reason.
64 fn poll_status(&mut self) -> Result<(), Self::StreamError>;
65
66 /// Return the amount of time that has elapsed from the instant
67 /// [`FirewheelProcessor::process_interleaved`] was last called and now.
68 ///
69 /// The given `process_timestamp` is the `Self::Instant` that was passed
70 /// to the latest call to [`FirewheelProcessor::process_interleaved`].
71 /// This can be used to calculate the delay if needed.
72 ///
73 /// If for any reason the delay could not be determined, return `None`.
74 fn delay_from_last_process(&self, process_timestamp: Self::Instant) -> Option<Duration>;
75}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct BackendProcessInfo<B: AudioBackend> {
79 pub num_in_channels: usize,
80 pub num_out_channels: usize,
81 pub frames: usize,
82 pub process_timestamp: B::Instant,
83 pub duration_since_stream_start: Duration,
84 pub input_stream_status: StreamStatus,
85 pub output_stream_status: StreamStatus,
86 pub dropped_frames: u32,
87}
88
89/// Basic information about an audio device. It contains the name of the
90/// device and a unique identifier that persists across reboots.
91#[derive(Default, Debug, Clone, PartialEq)]
92#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
93#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
94pub struct DeviceInfoSimple {
95 /// The display name of this audio device.
96 pub name: String,
97
98 /// A unique identifier for the device, serialized into a string.
99 ///
100 /// This identifier persists across application restarts and system
101 /// reboots.
102 pub id: String,
103}
104
105/// The configuration of an input/output device for a [`SimpleStreamConfig`]
106#[derive(Default, Debug, Clone, PartialEq)]
107#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
108#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
109pub struct SimpleDeviceConfig {
110 /// The ID of the device to use. (The ID from [`DeviceInfoSimple::id`].)
111 ///
112 /// Set to `None` to use the default device.
113 ///
114 /// By default this is set to `None`.
115 pub device: Option<String>,
116
117 /// The number of channels to use. The backend may end up using a different
118 /// channel count if the given channel count is not supported.
119 ///
120 /// Set to `None` to use the default number of channels for the device.
121 ///
122 /// By default this is set to `None`.
123 pub channels: Option<usize>,
124}
125
126/// An easy-to-use, backend-agnostic configuration for an audio stream
127#[derive(Debug, Clone, PartialEq)]
128#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
129#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
130pub struct SimpleStreamConfig {
131 /// The configuration of the output audio device
132 pub output: SimpleDeviceConfig,
133
134 /// The configuration of the input audio device
135 ///
136 /// Set to `None` to not connect an input audio device.
137 ///
138 /// By default this is set to `None`.
139 pub input: Option<SimpleDeviceConfig>,
140
141 /// The block size (latency) to use. Set to `None` to use the device's default
142 /// block size. The backend may end up using a different block size if the given
143 /// block size is not supported.
144 ///
145 /// By default this is set to `Some(1024)`, which should be good enough for most
146 /// games.
147 ///
148 /// If your application is not a game and doesn't need low latency playback,
149 /// then prefer to set this to `None` to reduce system resources.
150 pub desired_block_frames: Option<u32>,
151
152 /// The sample rate to use. The backend may end up using a different sample
153 /// rate if the given sample rate is not supported.
154 ///
155 /// Set to `None` to use the device's default sample rate.
156 ///
157 /// By default this is set to `None`.
158 pub desired_sample_rate: Option<u32>,
159}
160
161impl Default for SimpleStreamConfig {
162 fn default() -> Self {
163 Self {
164 output: SimpleDeviceConfig::default(),
165 input: None,
166 desired_block_frames: Some(1024),
167 desired_sample_rate: None,
168 }
169 }
170}