summaryrefslogtreecommitdiff
path: root/graphics/src/audio/channel.rs
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/src/audio/channel.rs')
-rw-r--r--graphics/src/audio/channel.rs199
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);
+ }
+}