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
25mod playback_stats;
26pub use playback_stats::*;
27
28pub mod context;
29
30pub mod media_devices;
31pub mod media_recorder;
32pub mod media_streams;
33
34pub mod node;
35
36mod events;
37pub use events::*;
38
39mod message_port;
40pub use message_port::MessagePort;
41
42mod param;
43pub use param::*;
44
45mod periodic_wave;
46pub use periodic_wave::*;
47
48mod render;
49
50mod stats;
51
52mod spatial;
53pub use spatial::AudioListener;
54
55mod io;
56
57mod analysis;
58mod message;
59
60mod decoding;
61
62mod media_element;
63pub use media_element::MediaElement;
64
65mod resampling;
66pub mod worklet;
67
68#[repr(transparent)]
69pub(crate) struct AtomicF32 {
70 bits: AtomicU32,
71}
72
73impl std::fmt::Debug for AtomicF32 {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 f.write_fmt(format_args!("{}", self.load(Ordering::Relaxed)))
76 }
77}
78
79impl AtomicF32 {
80 #[must_use]
81 pub fn new(value: f32) -> Self {
82 Self {
83 bits: AtomicU32::new(value.to_bits()),
84 }
85 }
86
87 #[must_use]
88 pub fn load(&self, ordering: Ordering) -> f32 {
89 f32::from_bits(self.bits.load(ordering))
90 }
91
92 pub fn store(&self, value: f32, ordering: Ordering) {
93 self.bits.store(value.to_bits(), ordering);
94 }
95}
96
97#[repr(transparent)]
99pub(crate) struct AtomicF64 {
100 bits: AtomicU64,
101}
102
103impl std::fmt::Debug for AtomicF64 {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 f.write_fmt(format_args!("{}", self.load(Ordering::Relaxed)))
106 }
107}
108
109impl AtomicF64 {
110 #[must_use]
111 pub fn new(value: f64) -> Self {
112 Self {
113 bits: AtomicU64::new(value.to_bits()),
114 }
115 }
116
117 #[must_use]
118 pub fn load(&self, ordering: Ordering) -> f64 {
119 f64::from_bits(self.bits.load(ordering))
120 }
121
122 pub fn store(&self, value: f64, ordering: Ordering) {
123 self.bits.store(value.to_bits(), ordering);
124 }
125}
126
127#[track_caller]
145#[inline(always)]
146pub(crate) fn assert_valid_sample_rate(sample_rate: f32) {
147 let min_sample_rate = 3_000.;
148 let max_sample_rate = 768_000.;
149
150 assert!(
151 sample_rate >= min_sample_rate && sample_rate <= max_sample_rate,
152 "NotSupportedError - Invalid sample rate: {:?}, should be in the range [{:?}, {:?}]",
153 sample_rate,
154 min_sample_rate,
155 max_sample_rate,
156 );
157}
158
159#[track_caller]
168#[inline(always)]
169pub(crate) fn assert_valid_number_of_channels(number_of_channels: usize) {
170 assert!(
171 number_of_channels > 0 && number_of_channels <= MAX_CHANNELS,
172 "NotSupportedError - Invalid number of channels: {:?} is outside range [1, {:?}]",
173 number_of_channels,
174 MAX_CHANNELS
175 );
176}
177
178#[track_caller]
187#[inline(always)]
188pub(crate) fn assert_valid_channel_number(channel_number: usize, number_of_channels: usize) {
189 assert!(
190 channel_number < number_of_channels,
191 "IndexSizeError - Invalid channel number {:?} (number of channels: {:?})",
192 channel_number,
193 number_of_channels
194 );
195}
196
197#[track_caller]
205#[inline(always)]
206pub(crate) fn assert_valid_buffer_length(length: usize) {
207 assert!(
208 length > 0,
209 "NotSupportedError - Invalid length: {:?} is less than or equal to minimum bound (0)",
210 length,
211 );
212}
213
214#[track_caller]
223#[inline(always)]
224pub(crate) fn assert_valid_time_value(value: f64) {
225 assert!(
226 value.is_finite(),
227 "TypeError - The provided time value is non-finite.",
228 );
229
230 assert!(
231 value >= 0.,
232 "RangeError - The provided time value ({:?}) cannot be negative",
233 value
234 );
235}
236
237pub(crate) trait AudioBufferIter: Iterator<Item = FallibleBuffer> + Send + 'static {}
238
239impl<M: Iterator<Item = FallibleBuffer> + Send + 'static> AudioBufferIter for M {}
240
241type FallibleBuffer = Result<AudioBuffer, Box<dyn Error + Send + Sync>>;
242
243#[cfg(test)]
244mod tests {
245 use float_eq::assert_float_eq;
246
247 use super::*;
248
249 #[test]
250 fn test_atomic_f64() {
251 let f = AtomicF64::new(2.0);
252 assert_float_eq!(f.load(Ordering::SeqCst), 2.0, abs <= 0.);
253
254 f.store(3.0, Ordering::SeqCst);
255 assert_float_eq!(f.load(Ordering::SeqCst), 3.0, abs <= 0.);
256 }
257
258 #[test]
259 fn test_valid_sample_rate() {
260 assert_valid_sample_rate(48000.);
261 assert_valid_sample_rate(3_000.);
262 assert_valid_sample_rate(768_000.);
263 }
264
265 #[test]
266 #[should_panic]
267 fn test_invalid_sample_rate_too_small() {
268 assert_valid_sample_rate(2_999.);
269 }
270
271 #[test]
272 #[should_panic]
273 fn test_invalid_sample_rate_too_big() {
274 assert_valid_sample_rate(768_001.);
275 }
276
277 #[test]
278 #[should_panic]
279 fn test_invalid_number_of_channels_min() {
280 assert_valid_number_of_channels(0);
281 }
282
283 #[test]
284 #[should_panic]
285 fn test_invalid_number_of_channels_max() {
286 assert_valid_number_of_channels(33);
287 }
288
289 #[test]
290 fn test_valid_number_of_channels() {
291 assert_valid_number_of_channels(1);
292 assert_valid_number_of_channels(32);
293 }
294
295 #[test]
296 #[should_panic]
297 fn test_invalid_time_value_non_finite() {
298 assert_valid_time_value(f64::NAN);
299 }
300
301 #[test]
302 #[should_panic]
303 fn test_invalid_time_value_negative() {
304 assert_valid_time_value(-1.);
305 }
306
307 #[test]
308 fn test_valid_time_value() {
309 assert_valid_time_value(0.);
310 assert_valid_time_value(1.);
311 }
312}