1#![doc = include_str!("../README.md")]
2#![warn(rust_2018_idioms)]
3#![warn(rust_2021_compatibility)]
4#![warn(clippy::missing_panics_doc)]
5#![warn(clippy::clone_on_ref_ptr)]
6#![deny(trivial_numeric_casts)]
7#![deny(missing_debug_implementations)]
8
9use std::error::Error;
10use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
11
12pub(crate) const RENDER_QUANTUM_SIZE: usize = 128;
15
16pub const MAX_CHANNELS: usize = 32;
18
19mod buffer;
20pub use buffer::*;
21
22mod capacity;
23pub use capacity::*;
24
25pub mod context;
26
27pub mod media_devices;
28pub mod media_recorder;
29pub mod media_streams;
30
31pub mod node;
32
33mod events;
34pub use events::*;
35
36mod message_port;
37pub use message_port::MessagePort;
38
39mod param;
40pub use param::*;
41
42mod periodic_wave;
43pub use periodic_wave::*;
44
45mod render;
46
47mod spatial;
48pub use spatial::AudioListener;
49
50mod io;
51
52mod analysis;
53mod message;
54
55mod decoding;
56
57mod media_element;
58pub use media_element::MediaElement;
59
60mod resampling;
61pub mod worklet;
62
63#[repr(transparent)]
64pub(crate) struct AtomicF32 {
65 bits: AtomicU32,
66}
67
68impl std::fmt::Debug for AtomicF32 {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 f.write_fmt(format_args!("{}", self.load(Ordering::Relaxed)))
71 }
72}
73
74impl AtomicF32 {
75 #[must_use]
76 pub fn new(value: f32) -> Self {
77 Self {
78 bits: AtomicU32::new(value.to_bits()),
79 }
80 }
81
82 #[must_use]
83 pub fn load(&self, ordering: Ordering) -> f32 {
84 f32::from_bits(self.bits.load(ordering))
85 }
86
87 pub fn store(&self, value: f32, ordering: Ordering) {
88 self.bits.store(value.to_bits(), ordering);
89 }
90}
91
92#[repr(transparent)]
94pub(crate) struct AtomicF64 {
95 bits: AtomicU64,
96}
97
98impl std::fmt::Debug for AtomicF64 {
99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100 f.write_fmt(format_args!("{}", self.load(Ordering::Relaxed)))
101 }
102}
103
104impl AtomicF64 {
105 #[must_use]
106 pub fn new(value: f64) -> Self {
107 Self {
108 bits: AtomicU64::new(value.to_bits()),
109 }
110 }
111
112 #[must_use]
113 pub fn load(&self, ordering: Ordering) -> f64 {
114 f64::from_bits(self.bits.load(ordering))
115 }
116
117 pub fn store(&self, value: f64, ordering: Ordering) {
118 self.bits.store(value.to_bits(), ordering);
119 }
120}
121
122#[track_caller]
138#[inline(always)]
139pub(crate) fn assert_valid_sample_rate(sample_rate: f32) {
140 let min_sample_rate = 2_000.;
144 let max_sample_rate = 384_000.;
145
146 assert!(
147 sample_rate >= min_sample_rate && sample_rate <= max_sample_rate,
148 "NotSupportedError - Invalid sample rate: {:?}, should be in the range [{:?}, {:?}]",
149 sample_rate,
150 min_sample_rate,
151 max_sample_rate,
152 );
153}
154
155#[track_caller]
164#[inline(always)]
165pub(crate) fn assert_valid_number_of_channels(number_of_channels: usize) {
166 assert!(
167 number_of_channels > 0 && number_of_channels <= MAX_CHANNELS,
168 "NotSupportedError - Invalid number of channels: {:?} is outside range [1, {:?}]",
169 number_of_channels,
170 MAX_CHANNELS
171 );
172}
173
174#[track_caller]
183#[inline(always)]
184pub(crate) fn assert_valid_channel_number(channel_number: usize, number_of_channels: usize) {
185 assert!(
186 channel_number < number_of_channels,
187 "IndexSizeError - Invalid channel number {:?} (number of channels: {:?})",
188 channel_number,
189 number_of_channels
190 );
191}
192
193#[track_caller]
201#[inline(always)]
202pub(crate) fn assert_valid_buffer_length(length: usize) {
203 assert!(
204 length > 0,
205 "NotSupportedError - Invalid length: {:?} is less than or equal to minimum bound (0)",
206 length,
207 );
208}
209
210#[track_caller]
219#[inline(always)]
220pub(crate) fn assert_valid_time_value(value: f64) {
221 assert!(
222 value.is_finite(),
223 "TypeError - The provided time value is non-finite.",
224 );
225
226 assert!(
227 value >= 0.,
228 "RangeError - The provided time value ({:?}) cannot be negative",
229 value
230 );
231}
232
233pub(crate) trait AudioBufferIter: Iterator<Item = FallibleBuffer> + Send + 'static {}
234
235impl<M: Iterator<Item = FallibleBuffer> + Send + 'static> AudioBufferIter for M {}
236
237type FallibleBuffer = Result<AudioBuffer, Box<dyn Error + Send + Sync>>;
238
239#[cfg(test)]
240mod tests {
241 use float_eq::assert_float_eq;
242
243 use super::*;
244
245 #[test]
246 fn test_atomic_f64() {
247 let f = AtomicF64::new(2.0);
248 assert_float_eq!(f.load(Ordering::SeqCst), 2.0, abs <= 0.);
249
250 f.store(3.0, Ordering::SeqCst);
251 assert_float_eq!(f.load(Ordering::SeqCst), 3.0, abs <= 0.);
252 }
253
254 #[test]
255 #[should_panic]
256 fn test_invalid_sample_rate_too_small() {
257 assert_valid_sample_rate(1.);
260 }
261
262 #[test]
263 #[should_panic]
264 fn test_invalid_sample_rate_too_big() {
265 assert_valid_sample_rate(1_000_000.);
268 }
269
270 #[test]
271 fn test_valid_sample_rate() {
272 assert_valid_sample_rate(48000.);
273 }
274
275 #[test]
276 #[should_panic]
277 fn test_invalid_number_of_channels_min() {
278 assert_valid_number_of_channels(0);
279 }
280
281 #[test]
282 #[should_panic]
283 fn test_invalid_number_of_channels_max() {
284 assert_valid_number_of_channels(33);
285 }
286
287 #[test]
288 fn test_valid_number_of_channels() {
289 assert_valid_number_of_channels(1);
290 assert_valid_number_of_channels(32);
291 }
292
293 #[test]
294 #[should_panic]
295 fn test_invalid_time_value_non_finite() {
296 assert_valid_time_value(f64::NAN);
297 }
298
299 #[test]
300 #[should_panic]
301 fn test_invalid_time_value_negative() {
302 assert_valid_time_value(-1.);
303 }
304
305 #[test]
306 fn test_valid_time_value() {
307 assert_valid_time_value(0.);
308 assert_valid_time_value(1.);
309 }
310}