Skip to main content

rill_sampler/
wav.rs

1//! WAV file loading (feature-gated behind `"wav"`).
2//!
3//! Supports mono and stereo 16-bit PCM WAV files.
4
5use crate::buffer::SampleBuffer;
6use rill_core::prelude::Sample;
7
8/// Errors that can occur during WAV loading.
9#[derive(Debug)]
10pub enum WavError {
11    Io(std::io::Error),
12    Hound(String),
13    Format(String),
14}
15
16impl std::fmt::Display for WavError {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        match self {
19            WavError::Io(e) => write!(f, "IO error: {}", e),
20            WavError::Hound(s) => write!(f, "WAV decode error: {}", s),
21            WavError::Format(s) => write!(f, "Invalid WAV: {}", s),
22        }
23    }
24}
25
26impl std::error::Error for WavError {}
27
28impl From<std::io::Error> for WavError {
29    fn from(e: std::io::Error) -> Self {
30        WavError::Io(e)
31    }
32}
33
34impl From<hound::Error> for WavError {
35    fn from(e: hound::Error) -> Self {
36        WavError::Hound(e.to_string())
37    }
38}
39
40/// Load a WAV file into a `SampleBuffer<Sample>`.
41pub fn load_wav(path: &str) -> Result<SampleBuffer<Sample>, WavError> {
42    let mut reader = hound::WavReader::open(path)?;
43    let spec = reader.spec();
44
45    let channels = spec.channels as u16;
46    let sample_rate = spec.sample_rate as f32;
47    let bits_per_sample = spec.bits_per_sample;
48
49    if bits_per_sample != 16 {
50        return Err(WavError::Format(format!(
51            "Only 16-bit PCM supported, got {}-bit",
52            bits_per_sample
53        )));
54    }
55
56    if channels != 1 && channels != 2 {
57        return Err(WavError::Format(format!(
58            "Only mono/stereo supported, got {} channels",
59            channels
60        )));
61    }
62
63    let samples: Vec<i16> = reader.samples::<i16>().collect::<Result<Vec<_>, _>>().map_err(|e| {
64        WavError::Format(format!("Sample read error: {}", e))
65    })?;
66
67    let name = path.rsplit('/').next().unwrap_or(path);
68
69    if channels == 1 {
70        let data: Vec<Sample> = samples.into_iter().map(|s| s as Sample / 32768.0).collect();
71        Ok(SampleBuffer::mono(data, sample_rate, name))
72    } else {
73        let mut left = Vec::with_capacity(samples.len() / 2);
74        let mut right = Vec::with_capacity(samples.len() / 2);
75        for chunk in samples.chunks(2) {
76            left.push(chunk[0] as Sample / 32768.0);
77            right.push(chunk[1] as Sample / 32768.0);
78        }
79        Ok(SampleBuffer::stereo(left, right, sample_rate, name))
80    }
81}