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
use super::*;

/// Specifies a particular sample data format.
#[derive(Debug, Clone, Copy)]
pub struct AudioFormat(pub(crate) u16);
#[allow(missing_docs)]
impl AudioFormat {
  phantom_fields! {
    self.0: u16,
    bit_size: 0-7,
    floating: 8,
    big_endian: 12,
    signed: 15,
  }
  pub const S8: AudioFormat = AudioFormat(AUDIO_S8 as u16);
  pub const U8: AudioFormat = AudioFormat(AUDIO_U8 as u16);
  pub const S16LSB: AudioFormat = AudioFormat(AUDIO_S16LSB as u16);
  pub const S16MSB: AudioFormat = AudioFormat(AUDIO_S16MSB as u16);
  pub const S16SYS: AudioFormat = AudioFormat(AUDIO_S16SYS as u16);
  pub const S16: AudioFormat = AudioFormat(AUDIO_S16 as u16);
  pub const U16LSB: AudioFormat = AudioFormat(AUDIO_U16LSB as u16);
  pub const U16MSB: AudioFormat = AudioFormat(AUDIO_U16MSB as u16);
  pub const U16SYS: AudioFormat = AudioFormat(AUDIO_U16SYS as u16);
  pub const U16: AudioFormat = AudioFormat(AUDIO_U16 as u16);
  pub const S32LSB: AudioFormat = AudioFormat(AUDIO_S32LSB as u16);
  pub const S32MSB: AudioFormat = AudioFormat(AUDIO_S32MSB as u16);
  pub const S32SYS: AudioFormat = AudioFormat(AUDIO_S32SYS as u16);
  pub const S32: AudioFormat = AudioFormat(AUDIO_S32 as u16);
  pub const F32LSB: AudioFormat = AudioFormat(AUDIO_F32LSB as u16);
  pub const F32MSB: AudioFormat = AudioFormat(AUDIO_F32MSB as u16);
  pub const F32SYS: AudioFormat = AudioFormat(AUDIO_F32SYS as u16);
  pub const F32: AudioFormat = AudioFormat(AUDIO_F32 as u16);
}
impl From<SDL_AudioFormat> for AudioFormat {
  fn from(format: SDL_AudioFormat) -> Self {
    Self(format)
  }
}

/// Specifies a request to open an audio queue.
#[derive(Debug, Clone, Copy)]
pub struct DefaultAudioQueueRequest {
  /// Samples per second
  pub frequency: i32,
  /// Sample data format.
  pub format: AudioFormat,
  /// Number of channels. Supported values are 1, 2, 4, or 6.
  pub channels: u8,
  /// Must be a power of 2.
  pub samples: u16,
  /// Allow the audio device you get to have a different frequency
  pub allow_frequency_change: bool,
  /// Allow the audio device you get to have a different format
  pub allow_format_change: bool,
  /// Allow the audio device you get to have a different channel count
  pub allow_channels_change: bool,
}

/// Handle to an audio device in "queue" mode, and info about its settings.
#[derive(Debug)]
pub struct AudioQueue<'sdl> {
  pub(crate) dev: SDL_AudioDeviceID,
  pub(crate) frequency: i32,
  pub(crate) format: AudioFormat,
  pub(crate) channels: u8,
  pub(crate) silence: u8,
  pub(crate) sample_count: usize,
  pub(crate) buffer_size: usize,
  pub(crate) _marker: PhantomData<&'sdl SDLToken>,
}
impl<'sdl> Drop for AudioQueue<'sdl> {
  fn drop(&mut self) {
    unsafe { SDL_CloseAudioDevice(self.dev) }
  }
}
impl<'sdl> AudioQueue<'sdl> {
  /// Samples per second
  pub fn frequency(&self) -> i32 {
    self.frequency
  }
  /// Sample data format
  pub fn format(&self) -> AudioFormat {
    self.format
  }
  /// Channel count
  pub fn channels(&self) -> u8 {
    self.channels
  }
  /// Silence value
  pub fn silence(&self) -> u8 {
    self.silence
  }
  /// Samples in the buffer
  pub fn sample_count(&self) -> usize {
    self.sample_count
  }
  /// Size (in bytes) of the buffer
  pub fn buffer_size(&self) -> usize {
    self.buffer_size
  }
  /// Sets the device into paused state or not.
  pub fn set_paused(&self, pause_on: bool) {
    unsafe { SDL_PauseAudioDevice(self.dev, pause_on as i32) }
  }
  /// Gets the current number of bytes of queued audio.
  ///
  /// NOTE: this seems to be a somewhat unreliable metric. When the queue runs
  /// low SDL2 seems to automatically re-queue some silence for you, but that
  /// silence time counts into the queue size. In other words, if you just leave
  /// the queue playing without pushing any new audio the queued byte size never
  /// hits 0. The queue size will go to 0 as expected if you clear it while
  /// playback it paused.
  pub fn queued_audio_size(&self) -> usize {
    unsafe { SDL_GetQueuedAudioSize(self.dev) as usize }
  }
  /// Clears any queued data that has not yet been sent to the sound card.
  pub fn clear(&self) {
    unsafe { SDL_ClearQueuedAudio(self.dev) }
  }
  /// Pushes audio data into the queue.
  ///
  /// The size of the queue has no particular limit, but you can't queue more
  /// than `u32::MAX` bytes at once.
  pub fn queue_audio(&self, data: &[u8]) -> Result<(), String> {
    assert!(data.len() < core::u32::MAX as usize);
    let ptr = data.as_ptr() as *const c_void;
    let len = data.len() as u32;
    let err = unsafe { SDL_QueueAudio(self.dev, ptr, len) };
    if err == 0 {
      Ok(())
    } else {
      Err(get_error())
    }
  }
}