From 13b18e3d7186303a94431fedab582b63b11fe60b Mon Sep 17 00:00:00 2001 From: gered Date: Sun, 5 Jun 2022 18:29:57 -0400 Subject: [PATCH] convenience methods for playing/stopping specific audio channels --- examples/audio_playback/src/main.rs | 28 +++++++++++------ libretrogd/src/audio/mod.rs | 48 ++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/examples/audio_playback/src/main.rs b/examples/audio_playback/src/main.rs index 2e5216d..ee0b28d 100644 --- a/examples/audio_playback/src/main.rs +++ b/examples/audio_playback/src/main.rs @@ -7,6 +7,7 @@ use sdl2::keyboard::Scancode; use libretrogd::audio::*; use libretrogd::graphics::*; use libretrogd::system::*; +use libretrogd::utils::rnd_value; #[derive(Debug, Copy, Clone)] struct AudioChannelStatus { @@ -58,11 +59,13 @@ fn main() -> Result<()> { let mut is_running = true; - let sound1 = load_and_convert_wav(Path::new("./assets/pickup-coin.wav"), system.audio.spec())?; - let sound2 = load_and_convert_wav(Path::new("./assets/powerup.wav"), system.audio.spec())?; - let sound3 = load_and_convert_wav(Path::new("./assets/explosion.wav"), system.audio.spec())?; - let sound4 = load_and_convert_wav(Path::new("./assets/jump.wav"), system.audio.spec())?; - let sound5 = load_and_convert_wav(Path::new("./assets/laser-shoot.wav"), system.audio.spec())?; + let sounds = [ + load_and_convert_wav(Path::new("./assets/pickup-coin.wav"), system.audio.spec())?, + load_and_convert_wav(Path::new("./assets/powerup.wav"), system.audio.spec())?, + load_and_convert_wav(Path::new("./assets/explosion.wav"), system.audio.spec())?, + load_and_convert_wav(Path::new("./assets/jump.wav"), system.audio.spec())?, + load_and_convert_wav(Path::new("./assets/laser-shoot.wav"), system.audio.spec())?, + ]; let mut statuses = [AudioChannelStatus { size: 0, position: 0, playing: false }; NUM_CHANNELS]; @@ -80,29 +83,34 @@ fn main() -> Result<()> { } if system.keyboard.is_key_pressed(Scancode::Num1) { - audio_device.play_buffer(&sound1, false)?; + audio_device.play_buffer(&sounds[0], false)?; } if system.keyboard.is_key_pressed(Scancode::Num2) { - audio_device.play_buffer(&sound2, false)?; + audio_device.play_buffer(&sounds[1], false)?; } if system.keyboard.is_key_pressed(Scancode::Num3) { - audio_device.play_buffer(&sound3, false)?; + audio_device.play_buffer(&sounds[2], false)?; } if system.keyboard.is_key_pressed(Scancode::Num4) { - audio_device.play_buffer(&sound4, false)?; + audio_device.play_buffer(&sounds[3], false)?; } if system.keyboard.is_key_pressed(Scancode::Num5) { - audio_device.play_buffer(&sound5, false)?; + audio_device.play_buffer(&sounds[4], false)?; } if system.keyboard.is_key_pressed(Scancode::Num6) { audio_device.play_generator(SineWaveGenerator::new(), false); } + if system.keyboard.is_key_pressed(Scancode::Num7) { + let index = rnd_value(0, sounds.len() - 1); + audio_device.play_buffer_on_channel(7, &sounds[index], false)?; + } + for index in 0..NUM_CHANNELS { let channel = &audio_device[index]; let mut status = &mut statuses[index]; diff --git a/libretrogd/src/audio/mod.rs b/libretrogd/src/audio/mod.rs index 6a7a0b4..8e3cbba 100644 --- a/libretrogd/src/audio/mod.rs +++ b/libretrogd/src/audio/mod.rs @@ -188,6 +188,9 @@ impl AudioChannel { pub enum AudioDeviceError { #[error("That buffer's AudioSpec does not match the device's AudioSpec")] AudioSpecMismatch, + + #[error("The channel index {0} is out of range")] + ChannelIndexOutOfRange(usize), } pub struct AudioDevice { @@ -230,6 +233,15 @@ impl AudioDevice { self.channels.iter().any(|channel| channel.playing) } + pub fn stop_channel(&mut self, channel_index: usize) -> Result<(), AudioDeviceError> { + if channel_index >= NUM_CHANNELS { + Err(AudioDeviceError::ChannelIndexOutOfRange(channel_index)) + } else { + self.channels[channel_index].stop(); + Ok(()) + } + } + pub fn stop_all(&mut self) { for channel in self.channels.iter_mut() { channel.stop(); @@ -253,7 +265,27 @@ impl AudioDevice { } } - pub fn play_generator(&mut self, generator: impl AudioGenerator + 'static, loops: bool) -> Result, AudioDeviceError> { + pub fn play_buffer_on_channel( + &mut self, + channel_index: usize, + buffer: &AudioBuffer, + loops: bool, + ) -> Result<(), AudioDeviceError> { + if buffer.spec != self.spec { + Err(AudioDeviceError::AudioSpecMismatch) + } else if channel_index >= NUM_CHANNELS { + Err(AudioDeviceError::ChannelIndexOutOfRange(channel_index)) + } else { + self.channels[channel_index].play_buffer(buffer, loops); + Ok(()) + } + } + + pub fn play_generator( + &mut self, + generator: impl AudioGenerator + 'static, + loops: bool, + ) -> Result, AudioDeviceError> { if let Some(channel) = self.stopped_channels_iter_mut().next() { channel.play_generator(generator, loops); Ok(Some(channel)) @@ -262,6 +294,20 @@ impl AudioDevice { } } + pub fn play_generator_on_channel( + &mut self, + channel_index: usize, + generator: impl AudioGenerator + 'static, + loops: bool, + ) -> Result<(), AudioDeviceError> { + if channel_index >= NUM_CHANNELS { + Err(AudioDeviceError::ChannelIndexOutOfRange(channel_index)) + } else { + self.channels[channel_index].play_generator(generator, loops); + Ok(()) + } + } + #[inline] pub fn playing_channels_iter(&mut self) -> impl Iterator { self.channels.iter().filter(|channel| channel.playing)