1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
use bitflags::bitflags;
use std::ffi::CString;
bitflags! {
/// The native formats this device supports.
///
/// Support for signed integers and floats. Audio data fed to/from an RtAudio stream
/// is assumed to ALWAYS be in host byte order. The internal routines will
/// automatically take care of any necessary byte-swapping between the host format
/// and the soundcard. Thus, endian-ness is not a concern in the following format
/// definitions.
///
/// Note you can still start a stream with any format. RtAudio will just
/// automatically convert to/from the best native format.
#[repr(C)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct NativeFormats: rtaudio_sys::rtaudio_format_t {
/// 8-bit signed integer.
const SINT8 = rtaudio_sys::RTAUDIO_FORMAT_SINT8;
/// 16-bit signed integer.
const SINT16 = rtaudio_sys::RTAUDIO_FORMAT_SINT16;
/// 24-bit signed integer.
const SINT24 = rtaudio_sys::RTAUDIO_FORMAT_SINT24;
/// 32-bit signed integer.
const SINT32 = rtaudio_sys::RTAUDIO_FORMAT_SINT32;
/// 32-bit floating point number, normalized between plus/minus 1.0.
const FLOAT32 = rtaudio_sys::RTAUDIO_FORMAT_FLOAT32;
/// 64-bit floating point number, normalized between plus/minus 1.0.
const FLOAT64 = rtaudio_sys::RTAUDIO_FORMAT_FLOAT64;
}
}
/// The sample format type.
///
/// Support for signed integers and floats. Audio data fed to/from an RtAudio stream
/// is assumed to ALWAYS be in host byte order. The internal routines will
/// automatically take care of any necessary byte-swapping between the host format
/// and the soundcard. Thus, endian-ness is not a concern in the following format
/// definitions.
#[repr(usize)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SampleFormat {
/// 8-bit signed integer.
SInt8 = rtaudio_sys::RTAUDIO_FORMAT_SINT8 as usize,
/// 16-bit signed integer.
SInt16 = rtaudio_sys::RTAUDIO_FORMAT_SINT16 as usize,
/// 24-bit signed integer.
///
/// The endianness will always be in the host's native byte order.
SInt24 = rtaudio_sys::RTAUDIO_FORMAT_SINT24 as usize,
/// 32-bit signed integer.
SInt32 = rtaudio_sys::RTAUDIO_FORMAT_SINT32 as usize,
/// 32-bit floating point number, normalized between plus/minus 1.0.
#[default]
Float32 = rtaudio_sys::RTAUDIO_FORMAT_FLOAT32 as usize,
/// 64-bit floating point number, normalized between plus/minus 1.0.
Float64 = rtaudio_sys::RTAUDIO_FORMAT_FLOAT64 as usize,
}
impl SampleFormat {
pub fn to_raw(&self) -> rtaudio_sys::rtaudio_format_t {
match self {
SampleFormat::SInt8 => rtaudio_sys::RTAUDIO_FORMAT_SINT8,
SampleFormat::SInt16 => rtaudio_sys::RTAUDIO_FORMAT_SINT16,
SampleFormat::SInt24 => rtaudio_sys::RTAUDIO_FORMAT_SINT24,
SampleFormat::SInt32 => rtaudio_sys::RTAUDIO_FORMAT_SINT32,
SampleFormat::Float32 => rtaudio_sys::RTAUDIO_FORMAT_FLOAT32,
SampleFormat::Float64 => rtaudio_sys::RTAUDIO_FORMAT_FLOAT64,
}
}
}
bitflags! {
/// Stream option flags.
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct StreamFlags: rtaudio_sys::rtaudio_stream_flags_t {
/// Use non-interleaved buffers (default = interleaved).
const NONINTERLEAVED = rtaudio_sys::RTAUDIO_FLAGS_NONINTERLEAVED;
/// Attempt to set stream parameters for lowest possible latency, with the
/// possible expense of stream performance.
const MINIMIZE_LATENCY = rtaudio_sys::RTAUDIO_FLAGS_MINIMIZE_LATENCY;
/// Attempt to grab the device for exclusive use.
///
/// Note that this is not possible with all supported audio APIs.
const HOG_DEVICE = rtaudio_sys::RTAUDIO_FLAGS_HOG_DEVICE;
/// Attempt to select realtime scheduling (round-robin) for the callback thread.
const SCHEDULE_REALTIME = rtaudio_sys::RTAUDIO_FLAGS_SCHEDULE_REALTIME;
/// Attempt to open the "default" PCM device when using the ALSA API. Note that
/// this will override any specified input or output device index.
const ALSA_USE_DEFAULT = rtaudio_sys::RTAUDIO_FLAGS_ALSA_USE_DEFAULT;
/// Do not automatically connect ports (JACK only).
const JACK_DONT_CONNECT = rtaudio_sys::RTAUDIO_FLAGS_JACK_DONT_CONNECT;
}
}
impl Default for StreamFlags {
fn default() -> Self {
Self::empty()
}
}
bitflags! {
/// Stream status (over- or underflow) flags.
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct StreamStatus: rtaudio_sys::rtaudio_stream_status_t {
/// Input data was discarded because of an overflow condition at the driver.
const INPUT_OVERFLOW = rtaudio_sys::RTAUDIO_STATUS_INPUT_OVERFLOW;
/// The output buffer ran low, likely producing a break in the output sound.
const OUTPUT_UNDERFLOW = rtaudio_sys::RTAUDIO_STATUS_OUTPUT_UNDERFLOW;
}
}
#[repr(i32)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Api {
/// Search for a default working compiled API.
#[default]
Unspecified = rtaudio_sys::RTAUDIO_API_UNSPECIFIED as i32,
/// Macintosh OS-X Core Audio API.
MacOSXCore = rtaudio_sys::RTAUDIO_API_MACOSX_CORE as i32,
/// The Advanced Linux Sound Architecture API.
LinuxALSA = rtaudio_sys::RTAUDIO_API_LINUX_ALSA as i32,
/// The Jack Low-Latency Audio Server API.
UnixJack = rtaudio_sys::RTAUDIO_API_UNIX_JACK as i32,
/// The Linux PulseAudio API.
LinuxPulse = rtaudio_sys::RTAUDIO_API_LINUX_PULSE as i32,
/// The Linux Open Sound System API.
LinuxOSS = rtaudio_sys::RTAUDIO_API_LINUX_OSS as i32,
/// The Steinberg Audio Stream I/O API.
WindowsASIO = rtaudio_sys::RTAUDIO_API_WINDOWS_ASIO as i32,
/// The Microsoft WASAPI API.
WindowsWASAPI = rtaudio_sys::RTAUDIO_API_WINDOWS_WASAPI as i32,
/// The Microsoft DirectSound API.
WindowsDS = rtaudio_sys::RTAUDIO_API_WINDOWS_DS as i32,
/// A compilable but non-functional API.
Dummy = rtaudio_sys::RTAUDIO_API_DUMMY as i32,
}
impl Api {
/// Get the short lower-case name used for identification purposes.
///
/// This value is guaranteed to remain identical across library versions.
///
/// If the API is unknown, this will return `None`.
pub fn get_name(&self) -> String {
let index = self.to_raw();
// Safety: We assume that this function returns a valid C String.
let s = unsafe {
// For some odd reason, this is off by one.
let raw_s = rtaudio_sys::rtaudio_api_name(index);
crate::ffi_utils::c_str_ptr_to_string_lossy(raw_s)
.unwrap_or_else(|| String::from("error"))
};
s
}
/// Get the display name for the given API.
///
/// If the API is unknown, this will return `None`.
pub fn get_display_name(&self) -> String {
let index = self.to_raw();
// Safety: We assume that this function returns a valid C String.
let s = unsafe {
// For some odd reason, this is off by one.
let raw_s = rtaudio_sys::rtaudio_api_display_name(index);
crate::ffi_utils::c_str_ptr_to_string_lossy(raw_s)
.unwrap_or_else(|| String::from("error"))
};
s
}
/// Retrieve the API by its name (as given in Api::get_name()).
pub fn from_name(name: &str) -> Option<Api> {
let c_name = if let Ok(n) = CString::new(name) {
n
} else {
return None;
};
// Safe because we have constructed a valid C String.
let index = unsafe { rtaudio_sys::rtaudio_compiled_api_by_name(c_name.as_ptr()) };
if let Some(a) = Self::from_raw(index) {
if a == Api::Unspecified {
None
} else {
Some(a)
}
} else {
None
}
}
pub fn from_raw(a: rtaudio_sys::rtaudio_api_t) -> Option<Api> {
match a {
rtaudio_sys::RTAUDIO_API_UNSPECIFIED => Some(Api::Unspecified),
rtaudio_sys::RTAUDIO_API_MACOSX_CORE => Some(Api::MacOSXCore),
rtaudio_sys::RTAUDIO_API_LINUX_ALSA => Some(Api::LinuxALSA),
rtaudio_sys::RTAUDIO_API_UNIX_JACK => Some(Api::UnixJack),
rtaudio_sys::RTAUDIO_API_LINUX_PULSE => Some(Api::LinuxPulse),
rtaudio_sys::RTAUDIO_API_LINUX_OSS => Some(Api::LinuxOSS),
rtaudio_sys::RTAUDIO_API_WINDOWS_ASIO => Some(Api::WindowsASIO),
rtaudio_sys::RTAUDIO_API_WINDOWS_WASAPI => Some(Api::WindowsWASAPI),
rtaudio_sys::RTAUDIO_API_WINDOWS_DS => Some(Api::WindowsDS),
rtaudio_sys::RTAUDIO_API_DUMMY => Some(Api::Dummy),
_ => None,
}
}
pub fn to_raw(&self) -> rtaudio_sys::rtaudio_api_t {
*self as rtaudio_sys::rtaudio_api_t
}
}