feat(audio): add voltex_audio crate with AudioClip type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ members = [
|
||||
"examples/shadow_demo",
|
||||
"examples/ibl_demo",
|
||||
"crates/voltex_physics",
|
||||
"crates/voltex_audio",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
@@ -25,6 +26,7 @@ voltex_renderer = { path = "crates/voltex_renderer" }
|
||||
voltex_ecs = { path = "crates/voltex_ecs" }
|
||||
voltex_asset = { path = "crates/voltex_asset" }
|
||||
voltex_physics = { path = "crates/voltex_physics" }
|
||||
voltex_audio = { path = "crates/voltex_audio" }
|
||||
wgpu = "28.0"
|
||||
winit = "0.30"
|
||||
bytemuck = { version = "1", features = ["derive"] }
|
||||
|
||||
6
crates/voltex_audio/Cargo.toml
Normal file
6
crates/voltex_audio/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "voltex_audio"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
55
crates/voltex_audio/src/audio_clip.rs
Normal file
55
crates/voltex_audio/src/audio_clip.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
/// A loaded audio clip stored as normalized f32 PCM samples.
|
||||
#[derive(Debug)]
|
||||
pub struct AudioClip {
|
||||
/// Interleaved PCM samples in the range [-1.0, 1.0].
|
||||
pub samples: Vec<f32>,
|
||||
/// Number of samples per second (e.g. 44100).
|
||||
pub sample_rate: u32,
|
||||
/// Number of audio channels (1 = mono, 2 = stereo).
|
||||
pub channels: u16,
|
||||
}
|
||||
|
||||
impl AudioClip {
|
||||
/// Create a new AudioClip from raw f32 samples.
|
||||
pub fn new(samples: Vec<f32>, sample_rate: u32, channels: u16) -> Self {
|
||||
Self {
|
||||
samples,
|
||||
sample_rate,
|
||||
channels,
|
||||
}
|
||||
}
|
||||
|
||||
/// Total number of multi-channel frames.
|
||||
/// A frame contains one sample per channel.
|
||||
pub fn frame_count(&self) -> usize {
|
||||
self.samples.len() / self.channels as usize
|
||||
}
|
||||
|
||||
/// Duration in seconds.
|
||||
pub fn duration(&self) -> f32 {
|
||||
self.frame_count() as f32 / self.sample_rate as f32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn mono_clip() {
|
||||
// 44100 Hz, 1 channel, 1 second of silence
|
||||
let samples = vec![0.0f32; 44100];
|
||||
let clip = AudioClip::new(samples, 44100, 1);
|
||||
assert_eq!(clip.frame_count(), 44100);
|
||||
assert!((clip.duration() - 1.0).abs() < 1e-6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stereo_clip() {
|
||||
// 44100 Hz, 2 channels, 0.5 seconds
|
||||
let samples = vec![0.0f32; 44100]; // 44100 interleaved samples = 22050 frames
|
||||
let clip = AudioClip::new(samples, 44100, 2);
|
||||
assert_eq!(clip.frame_count(), 22050);
|
||||
assert!((clip.duration() - 0.5).abs() < 1e-6);
|
||||
}
|
||||
}
|
||||
7
crates/voltex_audio/src/lib.rs
Normal file
7
crates/voltex_audio/src/lib.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
pub mod audio_clip;
|
||||
pub mod wav;
|
||||
pub mod mixing;
|
||||
|
||||
pub use audio_clip::AudioClip;
|
||||
pub use wav::{parse_wav, generate_wav_bytes};
|
||||
pub use mixing::{PlayingSound, mix_sounds};
|
||||
Reference in New Issue
Block a user