diff options
Diffstat (limited to 'graphics/src/audio/mod.rs')
| -rw-r--r-- | graphics/src/audio/mod.rs | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/graphics/src/audio/mod.rs b/graphics/src/audio/mod.rs new file mode 100644 index 0000000..473c05b --- /dev/null +++ b/graphics/src/audio/mod.rs @@ -0,0 +1,91 @@ +//! The `audio` crate stores all audio assets that need to be loaded during runtime + +use std::time::{Duration, Instant}; + +use channel::{Channel, NoiseChannel, PulseChannel, TriangleChannel}; +use raylib::audio::RaylibAudio; + +use crate::audio::data::Data; + +mod channel; +mod data; +mod parse; +mod program; + +pub const TIME_SLICE: Duration = Duration::from_millis(1000 / 60); + +/// Holds each audio channel +pub struct Channels { + pub pulse_a: PulseChannel, + pub pulse_b: PulseChannel, + pub triangle: TriangleChannel, + pub noise: NoiseChannel, +} +impl Channels { + pub(crate) fn load() -> crate::Result<Self> { + // Phantom handle to the raylib audio subsystem + // Raylib doesnt use a handle, but the rust bindings + // have one to ensure memory safety. + // + // We must leak this handle after allocating it, + // if we dont then all audio will be unloaded :( + // + // NOTE: would this cause issues if `Audio::load` was + // called multiple times? + let handle = Box::leak(Box::new(RaylibAudio::init_audio_device()?)); + + let pulse_a = PulseChannel::load(handle)?; + pulse_a.set_volume(0.0); + pulse_a.play(); + let pulse_b = PulseChannel::load(handle)?; + pulse_b.set_volume(0.0); + pulse_b.play(); + let triangle = TriangleChannel::load(handle)?; + triangle.set_volume(0.0); + triangle.play(); + let noise = NoiseChannel::load(handle)?; + noise.set_volume(0.0); + noise.play(); + + Ok(Self { + pulse_a, + pulse_b, + triangle, + noise, + }) + } +} + +/// The `Audio` container initalizes the audio subsystem +/// for raylib, leaks it (to gurentee audio is statically loaded), +/// then loads all needed audio samples +pub struct Audio { + channels: Channels, + last: Instant, + pub data: Data, +} +impl Audio { + pub(crate) fn load() -> crate::Result<Self> { + let channels = Channels::load()?; + let last = Instant::now(); + let data = Data::load()?; + + Ok(Self { + channels, + last, + data, + }) + } + + pub fn update(&mut self) { + if self.last.elapsed() >= TIME_SLICE { + self.data.test.exec(&mut self.channels); + self.last = Instant::now(); + } + + self.channels.pulse_a.update(); + self.channels.pulse_b.update(); + self.channels.triangle.update(); + self.channels.noise.update(); + } +} |