1use rill_core::traits::SignalSlab;
6
7#[derive(Debug)]
9pub enum WavError {
10 Io(std::io::Error),
12 Hound(String),
14 Format(String),
16}
17
18impl std::fmt::Display for WavError {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 match self {
21 WavError::Io(e) => write!(f, "IO error: {}", e),
22 WavError::Hound(s) => write!(f, "WAV decode error: {}", s),
23 WavError::Format(s) => write!(f, "Invalid WAV: {}", s),
24 }
25 }
26}
27
28impl std::error::Error for WavError {}
29
30impl From<std::io::Error> for WavError {
31 fn from(e: std::io::Error) -> Self {
32 WavError::Io(e)
33 }
34}
35
36impl From<hound::Error> for WavError {
37 fn from(e: hound::Error) -> Self {
38 WavError::Hound(e.to_string())
39 }
40}
41
42pub fn load_slab(path: &str) -> Result<SignalSlab, WavError> {
49 let mut reader = hound::WavReader::open(path)?;
50 let spec = reader.spec();
51
52 let channels = spec.channels;
53 let sample_rate = spec.sample_rate as f32;
54 let bits = spec.bits_per_sample;
55
56 let num_frames = reader.duration() as usize;
57
58 let f32_samples: Vec<f32> = match bits {
59 16 => reader
60 .samples::<i16>()
61 .map(|r| r.map(|s| s as f32 / 32768.0))
62 .collect::<Result<Vec<_>, _>>()
63 .map_err(|e| WavError::Format(format!("Sample read error: {}", e)))?,
64 24 => {
65 const SCALE: f32 = 1.0 / 8388608.0;
66 reader
67 .samples::<i32>()
68 .map(|r| r.map(|s| s as f32 * SCALE))
69 .collect::<Result<Vec<_>, _>>()
70 .map_err(|e| WavError::Format(format!("Sample read error: {}", e)))?
71 }
72 other => {
73 return Err(WavError::Format(format!(
74 "Only 16/24-bit supported, got {}-bit",
75 other
76 )))
77 }
78 };
79
80 let mut slab_channels: Vec<Box<[f32]>> = Vec::with_capacity(channels as usize);
81 if channels == 1 {
82 slab_channels.push(f32_samples.into_boxed_slice());
83 } else {
84 let ch = channels as usize;
85 let mut per_channel: Vec<Vec<f32>> =
86 (0..ch).map(|_| Vec::with_capacity(num_frames)).collect();
87 for chunk in f32_samples.chunks(ch) {
88 for (i, &s) in chunk.iter().enumerate() {
89 per_channel[i].push(s);
90 }
91 }
92 for v in per_channel {
93 slab_channels.push(v.into_boxed_slice());
94 }
95 }
96
97 Ok(SignalSlab {
98 channels: slab_channels,
99 sample_rate,
100 num_frames,
101 })
102}