summaryrefslogtreecommitdiff
path: root/graphics/src/audio/mod.rs
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-11-21 22:25:37 -0500
committerFreya Murphy <freya@freyacat.org>2025-11-21 22:25:37 -0500
commit654277d89471010f57794b8022385d2a99a15a14 (patch)
treec10f98cfae20517c23007b941214a4c5f34bfd51 /graphics/src/audio/mod.rs
parentdungeon: add chest usage/textures (diff)
downloadDungeonCrawl-654277d89471010f57794b8022385d2a99a15a14.tar.gz
DungeonCrawl-654277d89471010f57794b8022385d2a99a15a14.tar.bz2
DungeonCrawl-654277d89471010f57794b8022385d2a99a15a14.zip
audio: create orchestration system
Diffstat (limited to 'graphics/src/audio/mod.rs')
-rw-r--r--graphics/src/audio/mod.rs91
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();
+ }
+}