1use crate::buffer::SampleBuffer;
6use rill_core::prelude::Sample;
7
8#[derive(Debug)]
10pub enum WavError {
11 Io(std::io::Error),
13 Hound(String),
15 Format(String),
17}
18
19impl std::fmt::Display for WavError {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match self {
22 WavError::Io(e) => write!(f, "IO error: {}", e),
23 WavError::Hound(s) => write!(f, "WAV decode error: {}", s),
24 WavError::Format(s) => write!(f, "Invalid WAV: {}", s),
25 }
26 }
27}
28
29impl std::error::Error for WavError {}
30
31impl From<std::io::Error> for WavError {
32 fn from(e: std::io::Error) -> Self {
33 WavError::Io(e)
34 }
35}
36
37impl From<hound::Error> for WavError {
38 fn from(e: hound::Error) -> Self {
39 WavError::Hound(e.to_string())
40 }
41}
42
43pub fn load_wav(path: &str) -> Result<SampleBuffer<Sample>, WavError> {
47 let mut reader = hound::WavReader::open(path)?;
48 let spec = reader.spec();
49
50 let channels = spec.channels;
51 let sample_rate = spec.sample_rate as f32;
52 let bits_per_sample = spec.bits_per_sample;
53
54 if channels != 1 && channels != 2 {
55 return Err(WavError::Format(format!(
56 "Only mono/stereo supported, got {} channels",
57 channels
58 )));
59 }
60
61 let name = path.rsplit('/').next().unwrap_or(path).to_string();
62
63 match bits_per_sample {
64 16 => {
65 let samples: Vec<i16> = reader
66 .samples::<i16>()
67 .collect::<Result<Vec<_>, _>>()
68 .map_err(|e| WavError::Format(format!("Sample read error: {}", e)))?;
69 Ok(samples_to_buffer(
70 samples.into_iter().map(|s| s as f32 / 32768.0),
71 channels,
72 sample_rate,
73 name,
74 ))
75 }
76 24 => {
77 let samples: Vec<i32> = reader
78 .samples::<i32>()
79 .collect::<Result<Vec<_>, _>>()
80 .map_err(|e| WavError::Format(format!("Sample read error: {}", e)))?;
81 const SCALE: f32 = 1.0 / 8388608.0; Ok(samples_to_buffer(
83 samples.into_iter().map(|s| s as f32 * SCALE),
84 channels,
85 sample_rate,
86 name,
87 ))
88 }
89 other => Err(WavError::Format(format!(
90 "Only 16/24-bit PCM supported, got {}-bit",
91 other
92 ))),
93 }
94}
95
96fn samples_to_buffer(
97 samples: impl Iterator<Item = f32>,
98 channels: u16,
99 sample_rate: f32,
100 name: String,
101) -> SampleBuffer<Sample> {
102 let data: Vec<Sample> = samples.collect();
103 if channels == 1 {
104 SampleBuffer::mono(data, sample_rate, name)
105 } else {
106 let mut left = Vec::with_capacity(data.len() / 2);
107 let mut right = Vec::with_capacity(data.len() / 2);
108 for chunk in data.chunks(2) {
109 left.push(chunk[0]);
110 if chunk.len() > 1 {
111 right.push(chunk[1]);
112 }
113 }
114 SampleBuffer::stereo(left, right, sample_rate, name)
115 }
116}