convenience methods for playing/stopping specific audio channels

This commit is contained in:
Gered 2022-06-05 18:29:57 -04:00
parent 5f5bc79d86
commit 13b18e3d71
2 changed files with 65 additions and 11 deletions

View file

@ -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];

View file

@ -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<Option<&mut AudioChannel>, 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<Option<&mut AudioChannel>, 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<Item = &AudioChannel> {
self.channels.iter().filter(|channel| channel.playing)