pix_engine/audio.rs
1//! Trait and types for allowing [`Engine`] to play and capture audio.
2//!
3//! There are several methods for playing audio in your application:
4//!
5//! - Queuing pre-recorded or generated audio samples by calling [`PixState::enqueue_audio`].
6//! - Having [`Engine`] request pre-recorded or generated audio samples by implementing the
7//! [`AudioCallback`] trait on a type and calling [`PixState::open_playback`].
8//! - Loading and playing a `.wav` or `.mp3` file. (Coming soon!).
9//!
10//! You can also record audio from a capture device using [`PixState::open_capture`].
11//!
12//! [`Engine`]: crate::engine::Engine
13//!
14//! # Examples
15//!
16//! ## Audio Queue
17//!
18//! ```no_run
19//! use pix_engine::{prelude::*, math::PI};
20//!
21//! struct MyApp;
22//!
23//! impl PixEngine for MyApp {
24//! fn on_start(&mut self, s: &mut PixState) -> PixResult<()> {
25//! s.resume_audio();
26//! Ok(())
27//! }
28//!
29//! fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
30//! // Some square wave samples of audio
31//! let volume = 0.2;
32//! let sample_rate = s.audio_sample_rate() as f32;
33//! let sample_count = 4 * sample_rate as usize;
34//! let frequency = 440.0; // A4 note
35//! let mut samples = Vec::with_capacity(sample_count);
36//! for x in 0..sample_count {
37//! let s = (2.0 * PI as f32 * frequency * x as f32 / sample_rate).sin();
38//! samples.push(if s <= 0.0 { -volume } else { volume });
39//! }
40//! // Add samples to audio queue for playback
41//! s.enqueue_audio(&samples)?;
42//! Ok(())
43//! }
44//! }
45//! ```
46//!
47//! ## Audio Callback
48//!
49//! ```no_run
50//! use pix_engine::prelude::*;
51//! use std::time::Duration;
52//!
53//! struct SquareWave {
54//! phase_inc: f32,
55//! phase: f32,
56//! volume: f32,
57//! }
58//!
59//! impl AudioCallback for SquareWave {
60//! type Channel = f32;
61//!
62//! fn callback(&mut self, out: &mut [Self::Channel]) {
63//! // Generate a square wave
64//! for x in out.iter_mut() {
65//! *x = if self.phase <= 0.5 {
66//! self.volume
67//! } else {
68//! -self.volume
69//! };
70//! self.phase = (self.phase + self.phase_inc) % 1.0;
71//! }
72//! }
73//! }
74//!
75//! struct MyApp;
76//!
77//! impl PixEngine for MyApp {
78//! fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
79//! let desired_spec = AudioSpecDesired {
80//! freq: Some(44_100), // 44,100 HZ
81//! channels: Some(1), // mono audio
82//! samples: None, // default sample size
83//! };
84//! let mut device = s.open_playback(None, &desired_spec, |spec| {
85//! SquareWave {
86//! phase_inc: 440.0 / spec.freq as f32,
87//! phase: 0.0,
88//! volume: 0.25,
89//! }
90//! })?;
91//!
92//! // Start playback
93//! device.resume();
94//!
95//! // Play for 2 seconds then quit.
96//! std::thread::sleep(Duration::from_millis(2000));
97//! s.quit();
98//!
99//! // Device stops playback when dropped.
100//! Ok(())
101//! }
102//! }
103//! ```
104//!
105//! ## Audio Capture
106//!
107//! For a more complete example, see `audio_capture_and_replay` in the `examples/` directory.
108//!
109//! ```no_run
110//! use pix_engine::prelude::*;
111//! use std::{sync::mpsc, time::Duration};
112//!
113//! struct Recording {
114//! record_buffer: Vec<f32>,
115//! pos: usize,
116//! tx: mpsc::Sender<Vec<f32>>,
117//! done: bool,
118//! }
119//!
120//! impl AudioCallback for Recording {
121//! type Channel = f32;
122//!
123//! fn callback(&mut self, input: &mut [Self::Channel]) {
124//! if self.done {
125//! return;
126//! }
127//! for x in input {
128//! self.record_buffer[self.pos] = *x;
129//! self.pos += 1;
130//! if self.pos >= self.record_buffer.len() {
131//! self.done = true;
132//! self.tx
133//! .send(self.record_buffer.clone())
134//! .expect("could not send record buffer");
135//! break;
136//! }
137//! }
138//! }
139//! }
140//!
141//! struct MyApp;
142//!
143//! const RECORDING_LENGTH_SECONDS: usize = 3;
144//!
145//! impl PixEngine for MyApp {
146//! fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
147//! let desired_spec = AudioSpecDesired {
148//! freq: None, // default device frequency
149//! channels: None, // default device channels
150//! samples: None, // default sample size
151//! };
152//!
153//! let (tx, rx) = mpsc::channel();
154//! let capture_device = s.open_capture(None, &desired_spec, |spec| {
155//! Recording {
156//! record_buffer: vec![
157//! 0.0;
158//! spec.freq as usize
159//! * RECORDING_LENGTH_SECONDS
160//! * spec.channels as usize
161//! ],
162//! pos: 0,
163//! tx,
164//! done: false,
165//! }
166//! })?;
167//!
168//! // Start playback
169//! capture_device.resume();
170//!
171//! // Wait for recording to finish
172//! let recorded_samples = rx.recv()?;
173//! capture_device.pause();
174//!
175//! // Handle recorded_samples
176//!
177//! // Device stops playback when dropped.
178//! Ok(())
179//! }
180//! }
181//! ```
182//!
183//! [`PixEngine`]: crate::prelude::PixEngine
184
185use crate::prelude::*;
186#[cfg(feature = "serde")]
187use serde::{Deserialize, Serialize};
188
189#[cfg(not(target_arch = "wasm32"))]
190pub use crate::renderer::sdl::{AudioDevice, AudioFormatNum};
191
192#[cfg(target_arch = "wasm32")]
193pub use crate::renderer::wasm::{AudioDevice, AudioFormatNum};
194
195/// Trait for allowing [`Engine`] to request audio samples from your application.
196///
197/// Please see the [module-level documentation] for more examples.
198///
199/// [`Engine`]: crate::engine::Engine
200/// [module-level documentation]: crate::audio
201pub trait AudioCallback: Send
202where
203 Self::Channel: AudioFormatNum + 'static,
204{
205 /// The audio type format for channel samples.
206 type Channel;
207
208 /// Called when the audio playback device needs samples to play or the capture device has
209 /// samples available. `buffer` is a pre-allocated buffer you can iterate over and update to
210 /// provide audio samples, or consume to record audio samples.
211 ///
212 /// # Example
213 ///
214 /// ```
215 /// use pix_engine::prelude::*;
216 ///
217 /// struct SquareWave {
218 /// phase_inc: f32,
219 /// phase: f32,
220 /// volume: f32,
221 /// }
222 ///
223 /// impl AudioCallback for SquareWave {
224 /// type Channel = f32;
225 ///
226 /// fn callback(&mut self, out: &mut [Self::Channel]) {
227 /// // Generate a square wave
228 /// for x in out.iter_mut() {
229 /// *x = if self.phase <= 0.5 {
230 /// self.volume
231 /// } else {
232 /// -self.volume
233 /// };
234 /// self.phase = (self.phase + self.phase_inc) % 1.0;
235 /// }
236 /// }
237 /// }
238 /// ```
239 fn callback(&mut self, buffer: &mut [Self::Channel]);
240}
241
242/// Audio number and endianness format for the given audio device.
243#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
244#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
245#[must_use]
246pub enum AudioFormat {
247 /// Unsigned 8-bit samples
248 U8,
249 /// Signed 8-bit samples
250 S8,
251 /// Unsigned 16-bit samples, little-endian
252 U16LSB,
253 /// Unsigned 16-bit samples, big-endian
254 U16MSB,
255 /// Signed 16-bit samples, little-endian
256 S16LSB,
257 /// Signed 16-bit samples, big-endian
258 S16MSB,
259 /// Signed 32-bit samples, little-endian
260 S32LSB,
261 /// Signed 32-bit samples, big-endian
262 S32MSB,
263 /// 32-bit floating point samples, little-endian
264 F32LSB,
265 /// 32-bit floating point samples, big-endian
266 F32MSB,
267}
268
269#[cfg(target_endian = "little")]
270impl AudioFormat {
271 /// Unsigned 16-bit samples, native endian
272 #[inline]
273 pub const fn u16_sys() -> AudioFormat {
274 AudioFormat::U16LSB
275 }
276 /// Signed 16-bit samples, native endian
277 #[inline]
278 pub const fn s16_sys() -> AudioFormat {
279 AudioFormat::S16LSB
280 }
281 /// Signed 32-bit samples, native endian
282 #[inline]
283 pub const fn s32_sys() -> AudioFormat {
284 AudioFormat::S32LSB
285 }
286 /// 32-bit floating point samples, native endian
287 #[inline]
288 pub const fn f32_sys() -> AudioFormat {
289 AudioFormat::F32LSB
290 }
291}
292
293#[cfg(target_endian = "big")]
294impl AudioFormat {
295 /// Unsigned 16-bit samples, native endian
296 #[inline]
297 pub const fn u16_sys() -> AudioFormat {
298 AudioFormat::U16MSB
299 }
300 /// Signed 16-bit samples, native endian
301 #[inline]
302 pub const fn s16_sys() -> AudioFormat {
303 AudioFormat::S16MSB
304 }
305 /// Signed 32-bit samples, native endian
306 #[inline]
307 pub const fn s32_sys() -> AudioFormat {
308 AudioFormat::S32MSB
309 }
310 /// 32-bit floating point samples, native endian
311 #[inline]
312 pub const fn f32_sys() -> AudioFormat {
313 AudioFormat::F32MSB
314 }
315}
316
317impl Default for AudioFormat {
318 fn default() -> Self {
319 Self::f32_sys()
320 }
321}
322
323/// Playback status of an audio device.
324#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
325#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
326#[must_use]
327pub enum AudioStatus {
328 /// Audio device is stopped.
329 #[default]
330 Stopped,
331 /// Audio device is playing.
332 Playing,
333 /// Audio device is paused.
334 Paused,
335}
336
337/// Desired audio device specification.
338#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
339#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
340#[must_use]
341pub struct AudioSpecDesired {
342 /// DSP frequency (samples per second) in Hz. Set to None for the device’s fallback frequency.
343 pub freq: Option<i32>,
344 /// Number of separate sound channels. Set to None for the device’s fallback number of channels.
345 pub channels: Option<u8>,
346 /// The audio buffer size in samples (power of 2). Set to None for the device’s fallback sample size.
347 pub samples: Option<u16>,
348}
349
350/// Audio device specification.
351#[derive(Debug, Copy, Clone, PartialEq, Eq)]
352#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
353#[must_use]
354pub struct AudioSpec {
355 /// DSP frequency (samples per second) in Hz.
356 pub freq: i32,
357 /// `AudioFormat` for the generic sample type.
358 pub format: AudioFormat,
359 /// Number of separate sound channels.
360 pub channels: u8,
361 /// The audio buffer size in samples (power of 2).
362 pub samples: u16,
363 /// The audio buffer size in bytes.
364 pub size: u32,
365}
366
367impl Default for AudioSpec {
368 fn default() -> Self {
369 Self {
370 freq: 44_100,
371 format: AudioFormat::default(),
372 channels: 1,
373 samples: 512,
374 size: 2048,
375 }
376 }
377}
378
379/// Provides access to audio device driver properties and controlling playback.
380pub trait AudioDeviceDriver {
381 /// Return the status of this audio callback device.
382 fn status(&self) -> AudioStatus;
383
384 /// Return the current driver of this audio callback device.
385 fn driver(&self) -> &'static str;
386
387 /// Returns the [`AudioSpec`] for this audio callback device.
388 fn spec(&self) -> AudioSpec;
389
390 /// Resumes playback of this audio callback device.
391 fn resume(&self);
392
393 /// Pause playback of this audio callback device.
394 fn pause(&self);
395}
396
397impl PixState {
398 /// Add samples to the current audio buffer queue.
399 ///
400 /// # Errors
401 ///
402 /// If the audio device fails to queue samples, or if the audio buffer max size is reached,
403 /// then an error is returned.
404 ///
405 /// # Example
406 ///
407 /// ```
408 /// # use pix_engine::{math::PI, prelude::*};
409 /// # struct App;
410 /// # impl PixEngine for App {
411 /// fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
412 /// // Some square wave samples of audio
413 /// let volume = 0.2;
414 /// let sample_rate = s.audio_sample_rate() as f32;
415 /// let sample_count = 4 * sample_rate as usize;
416 /// let frequency = 440.0; // A4 note
417 /// let mut samples = Vec::with_capacity(sample_count);
418 /// for x in 0..sample_count {
419 /// let s = (2.0 * PI as f32 * frequency * x as f32 / sample_rate).sin();
420 /// samples.push(if s <= 0.0 { -volume } else { volume });
421 /// }
422 /// // Add samples to audio queue for playback
423 /// s.enqueue_audio(&samples)?;
424 /// Ok(())
425 /// }
426 /// # }
427 /// ```
428 #[inline]
429 pub fn enqueue_audio<S: AsRef<[f32]>>(&mut self, samples: S) -> PixResult<()> {
430 self.renderer.enqueue_audio(samples.as_ref())
431 }
432
433 /// Clear audio samples from the current audio buffer queue.
434 #[inline]
435 pub fn clear_audio(&mut self) {
436 self.renderer.clear_audio();
437 }
438
439 /// Return the status of the current audio queue device.
440 ///
441 /// # Example
442 ///
443 /// ```
444 /// # use pix_engine::prelude::*;
445 /// # struct App;
446 /// # impl PixEngine for App {
447 /// # fn on_update(&mut self, s: &mut PixState) -> PixResult<()> { Ok(()) }
448 /// fn on_key_pressed(&mut self, s: &mut PixState, event: KeyEvent) -> PixResult<bool> {
449 /// match event.key {
450 /// Key::Return => {
451 /// if s.audio_status() == AudioStatus::Paused {
452 /// s.resume_audio();
453 /// }
454 /// Ok(true)
455 /// }
456 /// _ => Ok(false),
457 /// }
458 /// }
459 /// # }
460 /// ```
461 #[inline]
462 pub fn audio_status(&self) -> AudioStatus {
463 self.renderer.audio_status()
464 }
465
466 /// Return the current driver of this audio callback device.
467 #[inline]
468 #[must_use]
469 pub fn audio_driver(&self) -> &'static str {
470 self.renderer.audio_driver()
471 }
472
473 /// Returns the sample rate for the current audio queue device.
474 #[inline]
475 #[must_use]
476 pub fn audio_sample_rate(&self) -> i32 {
477 self.renderer.audio_sample_rate()
478 }
479
480 /// Returns the queued buffer size of the current audio queue device.
481 #[inline]
482 #[must_use]
483 pub fn audio_queued_size(&self) -> u32 {
484 self.renderer.audio_queued_size()
485 }
486
487 /// Returns the buffer size of the current audio queue device.
488 #[inline]
489 #[must_use]
490 pub fn audio_size(&self) -> u32 {
491 self.renderer.audio_size()
492 }
493
494 /// Resumes playback of the current audio queue device.
495 ///
496 /// # Example
497 ///
498 /// ```
499 /// # use pix_engine::prelude::*;
500 /// # struct App;
501 /// # impl PixEngine for App {
502 /// # fn on_update(&mut self, s: &mut PixState) -> PixResult<()> { Ok(()) }
503 /// fn on_key_pressed(&mut self, s: &mut PixState, event: KeyEvent) -> PixResult<bool> {
504 /// match event.key {
505 /// Key::Return => {
506 /// s.resume_audio();
507 /// Ok(true)
508 /// }
509 /// _ => Ok(false),
510 /// }
511 /// }
512 /// # }
513 /// ```
514 #[inline]
515 pub fn resume_audio(&mut self) {
516 self.renderer.resume_audio();
517 }
518
519 /// Pause playback of the current audio queue device.
520 ///
521 /// # Example
522 ///
523 /// ```
524 /// # use pix_engine::prelude::*;
525 /// # struct App;
526 /// # impl PixEngine for App {
527 /// # fn on_update(&mut self, s: &mut PixState) -> PixResult<()> { Ok(()) }
528 /// fn on_key_pressed(&mut self, s: &mut PixState, event: KeyEvent) -> PixResult<bool> {
529 /// match event.key {
530 /// Key::Return => {
531 /// s.pause_audio();
532 /// Ok(true)
533 /// }
534 /// _ => Ok(false),
535 /// }
536 /// }
537 /// # }
538 /// ```
539 #[inline]
540 pub fn pause_audio(&mut self) {
541 self.renderer.pause_audio();
542 }
543
544 /// Opens and returns an audio callback device for playback.
545 ///
546 /// The audio device starts out `paused`. Call [resume](`AudioDevice::resume`) to start
547 /// playback and [pause](`AudioDevice::pause`) to stop playback.
548 ///
549 /// # Errors
550 ///
551 /// If the renderer fails to open an audio device, then an error is returned.
552 ///
553 /// # Example
554 ///
555 /// ```no_run
556 /// use pix_engine::prelude::*;
557 /// use std::time::Duration;
558 ///
559 /// struct SquareWave {
560 /// phase_inc: f32,
561 /// phase: f32,
562 /// volume: f32,
563 /// }
564 ///
565 /// impl AudioCallback for SquareWave {
566 /// type Channel = f32;
567 ///
568 /// fn callback(&mut self, out: &mut [Self::Channel]) {
569 /// // Generate a square wave
570 /// for x in out.iter_mut() {
571 /// *x = if self.phase <= 0.5 {
572 /// self.volume
573 /// } else {
574 /// -self.volume
575 /// };
576 /// self.phase = (self.phase + self.phase_inc) % 1.0;
577 /// }
578 /// }
579 /// }
580 ///
581 /// struct MyApp;
582 ///
583 /// impl PixEngine for MyApp {
584 /// fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
585 /// let desired_spec = AudioSpecDesired {
586 /// freq: Some(44_100), // 44,100 HZ
587 /// channels: Some(1), // mono audio
588 /// samples: None, // default sample size
589 /// };
590 /// let mut device = s.open_playback(None, &desired_spec, |spec| {
591 /// SquareWave {
592 /// phase_inc: 440.0 / spec.freq as f32,
593 /// phase: 0.0,
594 /// volume: 0.25,
595 /// }
596 /// })?;
597 ///
598 /// // Start playback
599 /// device.resume();
600 ///
601 /// // Play for 2 seconds then quit.
602 /// std::thread::sleep(Duration::from_millis(2000));
603 /// s.quit();
604 ///
605 /// // Device stops playback when dropped.
606 /// Ok(())
607 /// }
608 /// }
609 /// ```
610 #[allow(single_use_lifetimes)]
611 #[inline]
612 pub fn open_playback<'a, CB, F, D>(
613 &self,
614 device: D,
615 desired_spec: &AudioSpecDesired,
616 get_callback: F,
617 ) -> PixResult<AudioDevice<CB>>
618 where
619 CB: AudioCallback,
620 F: FnOnce(AudioSpec) -> CB,
621 D: Into<Option<&'a str>>,
622 {
623 self.renderer
624 .open_playback(device, desired_spec, get_callback)
625 }
626
627 /// Opens and returns an audio capture device for recording.
628 ///
629 /// The audio device starts out `paused`. Call [resume](`AudioDevice::resume`) to start
630 /// recording and [pause](`AudioDevice::pause`) to stop recording.
631 ///
632 /// # Errors
633 ///
634 /// If the renderer fails to open an audio device, then an error is returned.
635 ///
636 /// # Example
637 ///
638 /// ```no_run
639 /// use pix_engine::prelude::*;
640 /// use std::{sync::mpsc, time::Duration};
641 ///
642 /// struct Recording {
643 /// record_buffer: Vec<f32>,
644 /// pos: usize,
645 /// tx: mpsc::Sender<Vec<f32>>,
646 /// done: bool,
647 /// }
648 ///
649 /// impl AudioCallback for Recording {
650 /// type Channel = f32;
651 ///
652 /// fn callback(&mut self, input: &mut [Self::Channel]) {
653 /// if self.done {
654 /// return;
655 /// }
656 /// for x in input {
657 /// self.record_buffer[self.pos] = *x;
658 /// self.pos += 1;
659 /// if self.pos >= self.record_buffer.len() {
660 /// self.done = true;
661 /// self.tx
662 /// .send(self.record_buffer.clone())
663 /// .expect("could not send record buffer");
664 /// break;
665 /// }
666 /// }
667 /// }
668 /// }
669 ///
670 /// struct MyApp;
671 ///
672 /// const RECORDING_LENGTH_SECONDS: usize = 3;
673 ///
674 /// impl PixEngine for MyApp {
675 /// fn on_update(&mut self, s: &mut PixState) -> PixResult<()> {
676 /// let desired_spec = AudioSpecDesired {
677 /// freq: None, // default device frequency
678 /// channels: None, // default device channels
679 /// samples: None, // default sample size
680 /// };
681 ///
682 /// let (tx, rx) = mpsc::channel();
683 /// let capture_device = s.open_capture(None, &desired_spec, |spec| {
684 /// Recording {
685 /// record_buffer: vec![
686 /// 0.0;
687 /// spec.freq as usize
688 /// * RECORDING_LENGTH_SECONDS
689 /// * spec.channels as usize
690 /// ],
691 /// pos: 0,
692 /// tx,
693 /// done: false,
694 /// }
695 /// })?;
696 ///
697 /// // Start playback
698 /// capture_device.resume();
699 ///
700 /// // Wait for recording to finish
701 /// let recorded_samples = rx.recv()?;
702 /// capture_device.pause();
703 ///
704 /// // Handle recorded_samples
705 ///
706 /// // Device stops playback when dropped.
707 /// Ok(())
708 /// }
709 /// }
710 /// ```
711 #[allow(single_use_lifetimes)]
712 #[inline]
713 pub fn open_capture<'a, CB, F, D>(
714 &self,
715 device: D,
716 desired_spec: &AudioSpecDesired,
717 get_callback: F,
718 ) -> PixResult<AudioDevice<CB>>
719 where
720 CB: AudioCallback,
721 F: FnOnce(AudioSpec) -> CB,
722 D: Into<Option<&'a str>>,
723 {
724 self.renderer
725 .open_capture(device, desired_spec, get_callback)
726 }
727}
728
729/// Trait representing audio support.
730pub(crate) trait AudioDriver {
731 /// Add audio samples to the current audio buffer queue.
732 fn enqueue_audio(&mut self, samples: &[f32]) -> PixResult<()>;
733
734 /// Clear audio samples from the current audio buffer queue.
735 fn clear_audio(&mut self);
736
737 /// Return the status of the current audio queue device.
738 fn audio_status(&self) -> AudioStatus;
739
740 /// Return the driver of current audio queue device.
741 fn audio_driver(&self) -> &'static str;
742
743 /// Return the sample rate of the current audio queue device.
744 fn audio_sample_rate(&self) -> i32;
745
746 /// Returns the queued buffer size (in bytes) of the current audio queue device.
747 fn audio_queued_size(&self) -> u32;
748
749 /// Returns the buffer size (in bytes) of the current audio queue device.
750 fn audio_size(&self) -> u32;
751
752 /// Resume playback of the current audio queue device.
753 fn resume_audio(&mut self);
754
755 /// Pause playback of the current audio queue device.
756 fn pause_audio(&mut self);
757
758 /// Opens and returns an audio callback device for playback.
759 #[allow(single_use_lifetimes)]
760 fn open_playback<'a, CB, F, D>(
761 &self,
762 device: D,
763 desired_spec: &AudioSpecDesired,
764 get_callback: F,
765 ) -> PixResult<AudioDevice<CB>>
766 where
767 CB: AudioCallback,
768 F: FnOnce(AudioSpec) -> CB,
769 D: Into<Option<&'a str>>;
770
771 /// Opens and returns an audio capture device for recording.
772 #[allow(single_use_lifetimes)]
773 fn open_capture<'a, CB, F, D>(
774 &self,
775 device: D,
776 desired_spec: &AudioSpecDesired,
777 get_callback: F,
778 ) -> PixResult<AudioDevice<CB>>
779 where
780 CB: AudioCallback,
781 F: FnOnce(AudioSpec) -> CB,
782 D: Into<Option<&'a str>>;
783}