Lightningbeam/daw-backend/src/audio/sample_loader.rs

317 lines
10 KiB
Rust

use symphonia::core::audio::{AudioBufferRef, Signal};
use symphonia::core::codecs::{DecoderOptions, CODEC_TYPE_NULL};
use symphonia::core::errors::Error as SymphoniaError;
use symphonia::core::formats::FormatOptions;
use symphonia::core::io::MediaSourceStream;
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;
use std::fs::File;
use std::path::Path;
/// Loaded audio sample data
#[derive(Debug, Clone)]
pub struct SampleData {
/// Audio samples (mono, f32 format)
pub samples: Vec<f32>,
/// Original sample rate
pub sample_rate: u32,
}
/// Load an audio file and decode it to mono f32 samples
pub fn load_audio_file(path: impl AsRef<Path>) -> Result<SampleData, String> {
let path = path.as_ref();
// Open the file
let file = File::open(path)
.map_err(|e| format!("Failed to open file: {}", e))?;
// Create a media source stream
let mss = MediaSourceStream::new(Box::new(file), Default::default());
// Create a hint to help the format registry guess the format
let mut hint = Hint::new();
if let Some(extension) = path.extension() {
if let Some(ext_str) = extension.to_str() {
hint.with_extension(ext_str);
}
}
// Probe the media source for a format
let format_opts = FormatOptions::default();
let metadata_opts = MetadataOptions::default();
let probed = symphonia::default::get_probe()
.format(&hint, mss, &format_opts, &metadata_opts)
.map_err(|e| format!("Failed to probe format: {}", e))?;
let mut format = probed.format;
// Find the first audio track
let track = format
.tracks()
.iter()
.find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
.ok_or_else(|| "No audio tracks found".to_string())?;
let track_id = track.id;
let sample_rate = track.codec_params.sample_rate.unwrap_or(48000);
// Create a decoder for the track
let dec_opts = DecoderOptions::default();
let mut decoder = symphonia::default::get_codecs()
.make(&track.codec_params, &dec_opts)
.map_err(|e| format!("Failed to create decoder: {}", e))?;
// Decode all packets
let mut all_samples = Vec::new();
loop {
// Get the next packet
let packet = match format.next_packet() {
Ok(packet) => packet,
Err(SymphoniaError::IoError(e)) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
// End of stream
break;
}
Err(e) => {
return Err(format!("Error reading packet: {}", e));
}
};
// Skip packets that don't belong to the selected track
if packet.track_id() != track_id {
continue;
}
// Decode the packet
let decoded = decoder
.decode(&packet)
.map_err(|e| format!("Failed to decode packet: {}", e))?;
// Convert to f32 samples and mix to mono
let samples = convert_to_mono_f32(&decoded);
all_samples.extend_from_slice(&samples);
}
Ok(SampleData {
samples: all_samples,
sample_rate,
})
}
/// Convert an audio buffer to mono f32 samples
fn convert_to_mono_f32(buf: &AudioBufferRef) -> Vec<f32> {
match buf {
AudioBufferRef::F32(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
// Already mono
mono.extend_from_slice(buf.chan(0));
} else {
// Mix down to mono by averaging all channels
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += buf.chan(ch)[frame];
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::U8(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push((sample as f32 - 128.0) / 128.0);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += (buf.chan(ch)[frame] as f32 - 128.0) / 128.0;
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::U16(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push((sample as f32 - 32768.0) / 32768.0);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += (buf.chan(ch)[frame] as f32 - 32768.0) / 32768.0;
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::U24(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push((sample.inner() as f32 - 8388608.0) / 8388608.0);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += (buf.chan(ch)[frame].inner() as f32 - 8388608.0) / 8388608.0;
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::U32(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push((sample as f32 - 2147483648.0) / 2147483648.0);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += (buf.chan(ch)[frame] as f32 - 2147483648.0) / 2147483648.0;
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::S8(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push(sample as f32 / 128.0);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += buf.chan(ch)[frame] as f32 / 128.0;
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::S16(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push(sample as f32 / 32768.0);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += buf.chan(ch)[frame] as f32 / 32768.0;
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::S24(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push(sample.inner() as f32 / 8388608.0);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += buf.chan(ch)[frame].inner() as f32 / 8388608.0;
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::S32(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push(sample as f32 / 2147483648.0);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += buf.chan(ch)[frame] as f32 / 2147483648.0;
}
mono.push(sum / channels as f32);
}
}
mono
}
AudioBufferRef::F64(buf) => {
let channels = buf.spec().channels.count();
let frames = buf.frames();
let mut mono = Vec::with_capacity(frames);
if channels == 1 {
for &sample in buf.chan(0) {
mono.push(sample as f32);
}
} else {
for frame in 0..frames {
let mut sum = 0.0;
for ch in 0..channels {
sum += buf.chan(ch)[frame] as f32;
}
mono.push(sum / channels as f32);
}
}
mono
}
}
}