diff options
Diffstat (limited to 'graphics/src/audio/channel.rs')
| -rw-r--r-- | graphics/src/audio/channel.rs | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/graphics/src/audio/channel.rs b/graphics/src/audio/channel.rs new file mode 100644 index 0000000..be12f75 --- /dev/null +++ b/graphics/src/audio/channel.rs @@ -0,0 +1,199 @@ +use raylib::audio::RaylibAudio; + +type Music = raylib::audio::Music<'static>; + +macro_rules! load_audio { + ($handle:expr, $filepath:expr) => {{ + let mut audio = if cfg!(any(feature = "static", target_arch = "wasm32")) { + let bytes = include_bytes!(concat!("../../../", $filepath)); + let vec = Vec::from(bytes); + $handle.new_music_from_memory(".wav", &vec)? + } else { + $handle.new_music($filepath)? + }; + audio.looping = true; + audio + }}; +} + +pub trait Channel { + fn stop(&self); + fn play(&self); + fn update(&self); + fn is_playing(&self) -> bool; + fn set_volume(&self, volume: f32); + fn set_pitch(&self, pitch: f32); +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DutyCycle { + Percent12, + Percent25, + Percent50, + Percent25Neg, +} + +pub struct PulseChannel { + pulse_12: Music, + pulse_25: Music, + pulse_50: Music, + pulse_75: Music, + duty: DutyCycle, +} +impl PulseChannel { + pub fn load(handle: &'static RaylibAudio) -> crate::Result<Self> { + Ok(Self { + pulse_12: load_audio!(handle, "assets/pulse_12.wav"), + pulse_25: load_audio!(handle, "assets/pulse_25.wav"), + pulse_50: load_audio!(handle, "assets/pulse_50.wav"), + pulse_75: load_audio!(handle, "assets/pulse_50.wav"), + duty: DutyCycle::Percent50, + }) + } + + pub fn set_duty(&mut self, duty: DutyCycle) { + self.duty = duty; + if self.is_playing() { + self.stop(); + self.play(); + } + } +} +impl Channel for PulseChannel { + fn stop(&self) { + self.pulse_12.stop_stream(); + self.pulse_25.stop_stream(); + self.pulse_50.stop_stream(); + self.pulse_75.stop_stream(); + } + + fn play(&self) { + use DutyCycle as D; + match self.duty { + D::Percent12 => self.pulse_12.play_stream(), + D::Percent25 => self.pulse_25.play_stream(), + D::Percent50 => self.pulse_50.play_stream(), + D::Percent25Neg => self.pulse_75.play_stream(), + } + } + + fn update(&self) { + self.pulse_12.update_stream(); + self.pulse_25.update_stream(); + self.pulse_50.update_stream(); + self.pulse_75.update_stream(); + } + + fn is_playing(&self) -> bool { + self.pulse_12.is_stream_playing() + || self.pulse_25.is_stream_playing() + || self.pulse_50.is_stream_playing() + || self.pulse_75.is_stream_playing() + } + + fn set_volume(&self, volume: f32) { + self.pulse_12.set_volume(volume); + self.pulse_25.set_volume(volume); + self.pulse_50.set_volume(volume); + self.pulse_75.set_volume(volume); + } + + fn set_pitch(&self, pitch: f32) { + self.pulse_12.set_pitch(pitch); + self.pulse_25.set_pitch(pitch); + self.pulse_50.set_pitch(pitch); + self.pulse_75.set_pitch(pitch); + } +} + +pub struct TriangleChannel { + inner: Music, +} +impl TriangleChannel { + pub fn load(handle: &'static RaylibAudio) -> crate::Result<Self> { + Ok(Self { + inner: load_audio!(handle, "assets/triangle.wav"), + }) + } +} +impl Channel for TriangleChannel { + fn stop(&self) { + self.inner.stop_stream(); + } + + fn play(&self) { + self.inner.play_stream(); + } + + fn update(&self) { + self.inner.update_stream(); + } + + fn is_playing(&self) -> bool { + self.inner.is_stream_playing() + } + + fn set_volume(&self, volume: f32) { + self.inner.set_volume(volume); + } + + fn set_pitch(&self, pitch: f32) { + self.inner.set_pitch(pitch); + } +} + +pub struct NoiseChannel { + noise_0: Music, + noise_1: Music, + mode: bool, +} +impl NoiseChannel { + pub fn load(handle: &'static RaylibAudio) -> crate::Result<Self> { + Ok(Self { + noise_0: load_audio!(handle, "assets/noise_0.wav"), + noise_1: load_audio!(handle, "assets/noise_1.wav"), + mode: false, + }) + } + + pub fn set_mode(&mut self, mode: bool) { + self.mode = mode; + if self.is_playing() { + self.stop(); + self.play(); + } + } +} +impl Channel for NoiseChannel { + fn stop(&self) { + self.noise_0.stop_stream(); + self.noise_1.stop_stream(); + } + + fn play(&self) { + if self.mode { + self.noise_1.play_stream(); + } else { + self.noise_0.play_stream(); + } + } + + fn update(&self) { + self.noise_0.update_stream(); + self.noise_0.update_stream(); + } + + fn is_playing(&self) -> bool { + self.noise_0.is_stream_playing() || self.noise_1.is_stream_playing() + } + + fn set_volume(&self, volume: f32) { + self.noise_0.set_volume(volume); + self.noise_1.set_volume(volume); + } + + fn set_pitch(&self, pitch: f32) { + self.noise_0.set_pitch(pitch); + self.noise_1.set_pitch(pitch); + } +} |