Skip to content

Commit f5bd085

Browse files
committed
[add] example which plays our slash sound.
1 parent 5d43a86 commit f5bd085

5 files changed

Lines changed: 115 additions & 4 deletions

File tree

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ members = [
88
"crates/lambda-rs-logging",
99
"crates/lambda-rs-platform",
1010
"tools/obj_loader",
11+
"tools/lambda_audio",
1112
]
1213

1314
default-members = [
@@ -16,4 +17,5 @@ default-members = [
1617
"crates/lambda-rs-logging",
1718
"crates/lambda-rs-platform",
1819
"tools/obj_loader",
20+
"tools/lambda_audio",
1921
]
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#![allow(clippy::needless_return)]
2+
3+
use std::{
4+
sync::{
5+
atomic::{
6+
AtomicUsize,
7+
Ordering,
8+
},
9+
Arc,
10+
},
11+
time::Duration,
12+
};
13+
14+
use lambda::audio::{
15+
AudioOutputDeviceBuilder,
16+
SoundBuffer,
17+
};
18+
19+
#[cfg(all(
20+
feature = "audio-output-device",
21+
feature = "audio-sound-buffer-vorbis"
22+
))]
23+
fn main() {
24+
const SLASH_VORBIS_STEREO_48000_OGG: &[u8] = include_bytes!(concat!(
25+
env!("CARGO_MANIFEST_DIR"),
26+
"/../lambda-rs-platform/assets/audio/slash_vorbis_stereo_48000.ogg"
27+
));
28+
29+
let buffer =
30+
SoundBuffer::from_ogg_bytes(SLASH_VORBIS_STEREO_48000_OGG).unwrap();
31+
32+
let cursor = Arc::new(AtomicUsize::new(0));
33+
let buffer = Arc::new(buffer);
34+
35+
let cursor_for_callback = cursor.clone();
36+
let buffer_for_callback = buffer.clone();
37+
38+
let _device = AudioOutputDeviceBuilder::new()
39+
.with_label("play-slash-sound")
40+
.with_sample_rate(buffer.sample_rate())
41+
.with_channels(buffer.channels())
42+
.build_with_output_callback(move |writer, _info| {
43+
let writer_channels = writer.channels() as usize;
44+
let writer_frames = writer.frames();
45+
46+
writer.clear();
47+
48+
if writer_channels == 0 {
49+
return;
50+
}
51+
52+
let write_samples = writer_frames.saturating_mul(writer_channels);
53+
let start =
54+
cursor_for_callback.fetch_add(write_samples, Ordering::Relaxed);
55+
56+
let source_samples = buffer_for_callback.samples();
57+
58+
for frame in 0..writer_frames {
59+
for channel in 0..writer_channels {
60+
let sample_index = start
61+
.saturating_add(frame.saturating_mul(writer_channels))
62+
.saturating_add(channel);
63+
let value = source_samples.get(sample_index).copied().unwrap_or(0.0);
64+
writer.set_sample(frame, channel, value);
65+
}
66+
}
67+
68+
return;
69+
})
70+
.unwrap();
71+
72+
std::thread::sleep(Duration::from_secs_f32(buffer.duration_seconds() + 0.20));
73+
drop(_device);
74+
return;
75+
}
76+
77+
#[cfg(not(all(
78+
feature = "audio-output-device",
79+
feature = "audio-sound-buffer-vorbis"
80+
)))]
81+
fn main() {
82+
eprintln!(
83+
"this example requires `audio-output-device` and `audio-sound-buffer-vorbis`"
84+
);
85+
return;
86+
}

crates/lambda-rs/src/audio/buffer.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ impl SoundBuffer {
8383
return self.channels;
8484
}
8585

86+
/// Return interleaved `f32` samples in nominal range `[-1.0, 1.0]`.
87+
pub fn samples(&self) -> &[f32] {
88+
return self.samples.as_slice();
89+
}
90+
91+
/// Return the number of frames in this buffer.
92+
pub fn frames(&self) -> usize {
93+
if self.channels == 0 {
94+
return 0;
95+
}
96+
97+
return self.samples.len() / self.channels as usize;
98+
}
99+
86100
pub fn duration_seconds(&self) -> f32 {
87101
if self.channels == 0 || self.sample_rate == 0 {
88102
return 0.0;

docs/specs/audio-file-loading.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ title: "Audio File Loading (SoundBuffer)"
33
document_id: "audio-file-loading-2026-01-31"
44
status: "draft"
55
created: "2026-01-31T22:07:49Z"
6-
last_updated: "2026-01-31T23:03:17Z"
7-
version: "0.2.0"
6+
last_updated: "2026-02-02T17:40:16Z"
7+
version: "0.2.1"
88
engine_workspace_version: "2023.1.30"
99
wgpu_version: "26.0.1"
1010
shader_backend_default: "naga"
1111
winit_version: "0.29.10"
12-
repo_commit: "7cf8891f861a625b989f3751fd61674d072a53fe"
12+
repo_commit: "5d43a864febd72111671a4fab701cb0e5d2538b6"
1313
owners: ["lambda-sh"]
1414
reviewers: ["engine", "rendering"]
1515
tags: ["spec", "audio", "lambda-rs", "platform", "assets"]
@@ -175,6 +175,8 @@ impl SoundBuffer {
175175

176176
pub fn sample_rate(&self) -> u32;
177177
pub fn channels(&self) -> u16;
178+
pub fn samples(&self) -> &[f32];
179+
pub fn frames(&self) -> usize;
178180
pub fn duration_seconds(&self) -> f32;
179181
}
180182
```
@@ -296,7 +298,7 @@ Recommendations
296298
- Tests
297299
- [ ] Unit tests cover WAV mono and stereo
298300
- [ ] Unit tests cover OGG Vorbis mono and stereo
299-
- [ ] Test assets are stored under `crates/lambda-rs/assets/`
301+
- [ ] Test assets are stored under `crates/lambda-rs-platform/assets/audio/`
300302

301303
For each checked item, include a reference to a commit, pull request, or file
302304
path that demonstrates the implementation.

0 commit comments

Comments
 (0)