Skip to content

Commit ad962e9

Browse files
committed
[add] better documentation to public audio apis.
1 parent acaa047 commit ad962e9

3 files changed

Lines changed: 199 additions & 0 deletions

File tree

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

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ pub struct SoundBuffer {
1414
}
1515

1616
impl SoundBuffer {
17+
/// Decode a WAV file from disk into an in-memory sound buffer.
18+
///
19+
/// This method is available when the `audio-sound-buffer-wav` feature is
20+
/// enabled.
21+
///
22+
/// # Arguments
23+
/// - `path`: Path to a WAV file on disk.
24+
///
25+
/// # Returns
26+
/// A fully decoded sound buffer with interleaved `f32` samples.
27+
///
28+
/// # Errors
29+
/// Returns [`AudioError::Io`] if the file cannot be read. Returns
30+
/// [`AudioError::UnsupportedFormat`], [`AudioError::InvalidData`], or
31+
/// [`AudioError::DecodeFailed`] if decoding fails.
1732
#[cfg(feature = "audio-sound-buffer-wav")]
1833
pub fn from_wav_file(path: &Path) -> Result<Self, AudioError> {
1934
let bytes = std::fs::read(path).map_err(|error| {
@@ -26,13 +41,42 @@ impl SoundBuffer {
2641
return Self::from_wav_bytes(&bytes);
2742
}
2843

44+
/// Decode WAV container bytes into an in-memory sound buffer.
45+
///
46+
/// This method is available when the `audio-sound-buffer-wav` feature is
47+
/// enabled.
48+
///
49+
/// # Arguments
50+
/// - `bytes`: Full WAV container bytes.
51+
///
52+
/// # Returns
53+
/// A fully decoded sound buffer with interleaved `f32` samples.
54+
///
55+
/// # Errors
56+
/// Returns [`AudioError::UnsupportedFormat`], [`AudioError::InvalidData`], or
57+
/// [`AudioError::DecodeFailed`] if decoding fails.
2958
#[cfg(feature = "audio-sound-buffer-wav")]
3059
pub fn from_wav_bytes(bytes: &[u8]) -> Result<Self, AudioError> {
3160
let decoded = lambda_platform::audio::symphonia::decode_wav_bytes(bytes)
3261
.map_err(map_decode_error)?;
3362
return Self::from_decoded(decoded);
3463
}
3564

65+
/// Decode an OGG Vorbis file from disk into an in-memory sound buffer.
66+
///
67+
/// This method is available when the `audio-sound-buffer-vorbis` feature is
68+
/// enabled.
69+
///
70+
/// # Arguments
71+
/// - `path`: Path to an OGG Vorbis file on disk.
72+
///
73+
/// # Returns
74+
/// A fully decoded sound buffer with interleaved `f32` samples.
75+
///
76+
/// # Errors
77+
/// Returns [`AudioError::Io`] if the file cannot be read. Returns
78+
/// [`AudioError::UnsupportedFormat`], [`AudioError::InvalidData`], or
79+
/// [`AudioError::DecodeFailed`] if decoding fails.
3680
#[cfg(feature = "audio-sound-buffer-vorbis")]
3781
pub fn from_ogg_file(path: &Path) -> Result<Self, AudioError> {
3882
let bytes = std::fs::read(path).map_err(|error| {
@@ -45,6 +89,20 @@ impl SoundBuffer {
4589
return Self::from_ogg_bytes(&bytes);
4690
}
4791

92+
/// Decode OGG Vorbis container bytes into an in-memory sound buffer.
93+
///
94+
/// This method is available when the `audio-sound-buffer-vorbis` feature is
95+
/// enabled.
96+
///
97+
/// # Arguments
98+
/// - `bytes`: Full OGG container bytes.
99+
///
100+
/// # Returns
101+
/// A fully decoded sound buffer with interleaved `f32` samples.
102+
///
103+
/// # Errors
104+
/// Returns [`AudioError::UnsupportedFormat`], [`AudioError::InvalidData`], or
105+
/// [`AudioError::DecodeFailed`] if decoding fails.
48106
#[cfg(feature = "audio-sound-buffer-vorbis")]
49107
pub fn from_ogg_bytes(bytes: &[u8]) -> Result<Self, AudioError> {
50108
let decoded =
@@ -53,6 +111,18 @@ impl SoundBuffer {
53111
return Self::from_decoded(decoded);
54112
}
55113

114+
/// Convert platform decoded audio into the public sound buffer
115+
/// representation.
116+
///
117+
/// # Arguments
118+
/// - `decoded`: Decoded audio samples and associated metadata produced by the
119+
/// platform layer.
120+
///
121+
/// # Returns
122+
/// A sound buffer containing the provided samples and validated metadata.
123+
///
124+
/// # Errors
125+
/// Returns [`AudioError::InvalidData`] if the decoded metadata is invalid.
56126
fn from_decoded(
57127
decoded: lambda_platform::audio::symphonia::DecodedAudio,
58128
) -> Result<Self, AudioError> {
@@ -75,20 +145,34 @@ impl SoundBuffer {
75145
});
76146
}
77147

148+
/// Return the sample rate in Hz.
149+
///
150+
/// # Returns
151+
/// The sample rate in Hz.
78152
pub fn sample_rate(&self) -> u32 {
79153
return self.sample_rate;
80154
}
81155

156+
/// Return the interleaved channel count.
157+
///
158+
/// # Returns
159+
/// The channel count.
82160
pub fn channels(&self) -> u16 {
83161
return self.channels;
84162
}
85163

86164
/// Return interleaved `f32` samples in nominal range `[-1.0, 1.0]`.
165+
///
166+
/// # Returns
167+
/// A slice of interleaved samples.
87168
pub fn samples(&self) -> &[f32] {
88169
return self.samples.as_slice();
89170
}
90171

91172
/// Return the number of frames in this buffer.
173+
///
174+
/// # Returns
175+
/// The number of frames in the buffer.
92176
pub fn frames(&self) -> usize {
93177
if self.channels == 0 {
94178
return 0;
@@ -97,6 +181,10 @@ impl SoundBuffer {
97181
return self.samples.len() / self.channels as usize;
98182
}
99183

184+
/// Return the duration of the buffer in seconds.
185+
///
186+
/// # Returns
187+
/// The duration in seconds.
100188
pub fn duration_seconds(&self) -> f32 {
101189
if self.channels == 0 || self.sample_rate == 0 {
102190
return 0.0;
@@ -108,6 +196,13 @@ impl SoundBuffer {
108196
}
109197
}
110198

199+
/// Map platform decode errors into backend-agnostic public errors.
200+
///
201+
/// # Arguments
202+
/// - `error`: The platform decode error.
203+
///
204+
/// # Returns
205+
/// The equivalent public audio error.
111206
fn map_decode_error(
112207
error: lambda_platform::audio::symphonia::AudioDecodeError,
113208
) -> AudioError {
@@ -134,6 +229,7 @@ fn map_decode_error(
134229
mod tests {
135230
use super::*;
136231

232+
/// Duration computation MUST match frames / sample_rate.
137233
#[test]
138234
fn duration_seconds_computes_expected_value() {
139235
let buffer = SoundBuffer {
@@ -146,6 +242,7 @@ mod tests {
146242
return;
147243
}
148244

245+
/// WAV decode from bytes MUST succeed for the bundled fixture.
149246
#[cfg(feature = "audio-sound-buffer-wav")]
150247
#[test]
151248
fn from_wav_bytes_decodes_fixture() {
@@ -161,6 +258,7 @@ mod tests {
161258
return;
162259
}
163260

261+
/// WAV decode from file MUST succeed for the bundled fixture.
164262
#[cfg(feature = "audio-sound-buffer-wav")]
165263
#[test]
166264
fn from_wav_file_decodes_fixture() {
@@ -174,6 +272,7 @@ mod tests {
174272
return;
175273
}
176274

275+
/// OGG Vorbis decode from bytes MUST succeed for the bundled fixture.
177276
#[cfg(feature = "audio-sound-buffer-vorbis")]
178277
#[test]
179278
fn from_ogg_bytes_decodes_fixture() {
@@ -189,6 +288,7 @@ mod tests {
189288
return;
190289
}
191290

291+
/// OGG Vorbis decode from file MUST succeed for the bundled fixture.
192292
#[cfg(feature = "audio-sound-buffer-vorbis")]
193293
#[test]
194294
fn from_ogg_file_decodes_fixture() {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
#![allow(clippy::needless_return)]
22

3+
//! Audio device APIs.
4+
//!
5+
//! This module hosts device surfaces for audio input and output. Output is
6+
//! implemented first; input devices are expected to be added later.
7+
//!
8+
//! All public types in this module MUST remain backend-agnostic. Platform and
9+
//! vendor details are implemented in `lambda-rs-platform` and MUST NOT be
10+
//! exposed through this surface.
11+
312
pub mod output;

0 commit comments

Comments
 (0)