audio_master/backend/
backend.rs

1use std::{
2    hash::DefaultHasher,
3    sync::{Arc, RwLock},
4};
5
6use cpal::{PauseStreamError, PlayStreamError, SupportedStreamConfigRange};
7
8/// Audio host
9use crate::{
10    audio_buffer::{AudioBuffer, AudioChannelLayout},
11    float_type::FloatType,
12};
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum RawAudioStreamError {
16    DeviceNotAvailable,
17    Internal(String),
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub enum RawAudioStreamState {
22    Ok,
23
24    /// internal error occured.
25    /// Input buffer is filled with zero.
26    Err,
27
28    /// Input buffer is filled with zero.
29    Silence,
30
31    /// If an internal error occured.
32    /// Input buffer is filled with zero.
33    Other(String),
34}
35
36#[derive(Debug, Clone, PartialEq, Eq)]
37pub enum AudioHostError {
38    NoDevice,
39    NoConfig,
40    UnknownSampleFormat,
41    UnknownChannelCount,
42    UnknownStreamConfig,
43    DeviceNotAvailable,
44    InvalidArgument,
45    StreamIdOverflow,
46    UnknownError,
47    Internal(String),
48}
49
50#[derive(Debug, Clone)]
51pub struct Device {
52    pub name: String,
53    pub sample_rate: u32,
54    pub channels: AudioChannelLayout,
55    pub id: usize,
56}
57
58pub trait AudioHostImpl {
59    fn new() -> AudioHost;
60
61    /// Returns default output device set by system.
62    fn default_output_device(&self) -> Option<Device>;
63
64    /// Returns a device by id.
65    fn get_device_by_id(&self, id: usize) -> Result<Device, AudioHostError>;
66
67    /// Get availabe audio devices.
68    fn devices(&self) -> Vec<Device>;
69
70    /// Create a stream with default device. Float32 type.
71    /// If there's no devices returns AudioHostError::NoDevice.
72    fn create_stream_default(
73        &mut self,
74        feeder: Box<dyn StreamFeederTrait<f32>>,
75        buffer_size: usize,
76    ) -> Result<RawAudioStream<f32>, AudioHostError>;
77
78    /// Create a stream with specified device. Float64 type.
79    /// If there's no devices returns AudioHostError::NoDevice.
80    fn create_stream(
81        &mut self,
82        feeder: Box<dyn StreamFeederTrait<f32>>,
83        buffer_size: usize,
84        device_id: usize,
85    ) -> Result<RawAudioStream<f32>, AudioHostError>;
86}
87
88pub trait RawAudioStreamImpl: Sized {
89    /// Close stream.
90    /// Can be emitted by StreamFeederTrait::emit_stream_close().
91    fn close(&mut self);
92
93    /// Play stream.
94    /// Can be emitted by StreamFeederTrait::emit_stream_play().
95    fn play(&mut self) -> Result<(), RawAudioStreamError>;
96
97    /// Pause stream.
98    /// Can be emitted by StreamFeederTrait::emit_stream_pause().
99    fn pause(&mut self) -> Result<(), RawAudioStreamError>;
100
101    /// Is stream running
102    fn is_running(&self) -> bool;
103
104    /// Returns stream sample rate
105    fn get_sample_rate(&self) -> u32;
106
107    /// Returns timestamp in micro seconds
108    fn get_timestamp(&self) -> usize;
109}
110
111pub trait StreamFeederTrait<T: FloatType + Send + Sync> {
112    /// Main user processor.
113    fn process(&mut self, input: &mut AudioBuffer<T>) -> RawAudioStreamState;
114
115    /// Calls when an internal stream error occured, e.g - a device is turned off.
116    fn emit_stream_error(&mut self, error: &str);
117
118    /// Calls when a stream is being closed.
119    fn emit_stream_close(&mut self);
120
121    /// Calls when a stream is unpaused
122    fn emit_stream_play(&mut self);
123
124    /// Calls when a stream is paused
125    fn emit_stream_pause(&mut self);
126}
127
128#[derive(Clone)]
129pub struct AudioHost {
130    pub(super) core: Arc<RwLock<cpal::Host>>,
131}
132
133pub struct RawAudioStreamInner<T: FloatType> {
134    pub(super) core: Option<cpal::Stream>,
135    pub(super) is_running: bool,
136    pub(super) buffer: AudioBuffer<T>,
137    pub(super) buffer_offset: usize,
138    pub(super) sample_rate: u32,
139
140    /// sample_rate / 1000
141    /// Needed for timestamp fast calculation
142    pub(super) sample_rate_1000: f64,
143    pub(super) feeder: Box<dyn StreamFeederTrait<T>>,
144
145    /// Count of buffer sampled passed.
146    pub(super) timestamp: usize,
147}
148
149#[derive(Clone)]
150pub struct RawAudioStream<T: FloatType> {
151    pub(super) inner: Arc<RwLock<RawAudioStreamInner<T>>>,
152}
153
154pub trait PrivateImpl: Sized {
155    /// Converts channels count to channel layout.
156    fn channels_to_layout(channels: usize) -> Option<AudioChannelLayout>;
157
158    /// Converts cpal::PlayStreamError into RawAudioStreamError.
159    fn conv_cpal_play_stream_error(error: PlayStreamError) -> RawAudioStreamError;
160
161    /// Converts cpal::PauseStreamError into RawAudioStreamError.
162    fn conv_cpal_pause_stream_error(error: PauseStreamError) -> RawAudioStreamError;
163
164    /// Converts cpal::Device into Device.
165    fn cpal_device_to_device(device: cpal::Device) -> Option<Device>;
166
167    /// Generates id from cpol::Device.
168    /// Device's content used as ssid.
169    fn generate_id_from_cpal_device(device: &cpal::Device) -> i64;
170    fn hash_config_range(config: &SupportedStreamConfigRange, hasher: &mut DefaultHasher);
171}
172
173pub trait AudioHostPrivateImpl: Sized {
174    /// Try to find cpal::Device by id
175    fn get_cpal_device_by_id(&self, id: usize) -> Result<cpal::Device, AudioHostError>;
176
177    /// Try to create stream with specific device
178    fn create_stream_with_device<T: FloatType + Send + Sync + 'static>(
179        &mut self,
180        device: &cpal::Device,
181        buffer_size: usize,
182        feeder: Box<dyn StreamFeederTrait<T>>,
183    ) -> Result<Arc<RwLock<RawAudioStreamInner<T>>>, AudioHostError>;
184}
185
186pub trait RawAudioStreamPrivateImpl<T: FloatType + Send + Sync>: Sized {
187    /// Main process function for buffer size and channel layout alignments
188    fn user_cpal_process(&mut self, buffer: &mut [f32], channels: AudioChannelLayout);
189}
190
191pub struct Private {}