diff options
| author | Freya Murphy <freya@freyacat.org> | 2025-11-22 13:29:10 -0500 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2025-11-22 13:29:10 -0500 |
| commit | 2274d33e469aca544a7aeb899a10769b973ae374 (patch) | |
| tree | 7ff10964234fd5e8917624508e249265a3d0b19c /audio/src/lib.rs | |
| parent | audio: move 'asm' files out of data segment (diff) | |
| download | DungeonCrawl-2274d33e469aca544a7aeb899a10769b973ae374.tar.gz DungeonCrawl-2274d33e469aca544a7aeb899a10769b973ae374.tar.bz2 DungeonCrawl-2274d33e469aca544a7aeb899a10769b973ae374.zip | |
audio: refactor into seperate crate
Diffstat (limited to 'audio/src/lib.rs')
| -rw-r--r-- | audio/src/lib.rs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/audio/src/lib.rs b/audio/src/lib.rs new file mode 100644 index 0000000..b2d3e87 --- /dev/null +++ b/audio/src/lib.rs @@ -0,0 +1,97 @@ +//! The `audio` crate stores all audio assets that need to be loaded during runtime + +use raylib::audio::RaylibAudio; +use std::time::{Duration, Instant}; + +use channel::{Channel, NoiseChannel, PulseChannel, TriangleChannel}; +use data::Data; + +mod channel; +mod data; +mod parse; +mod program; + +/// The `Error` type used within this crate +pub type Error = Box<dyn std::error::Error>; + +/// The `Result` type used witin this crate +pub type Result<T> = std::result::Result<T, crate::Error>; + +const AUDIO_FPS: u32 = 60; +const TIME_SLICE: Duration = Duration::from_millis(1000 / AUDIO_FPS as u64); + +/// 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 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.megalovania.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(); + } +} |