rodio/decoder/
wav.rs
1use std::io::{Read, Seek, SeekFrom};
2use std::time::Duration;
3
4use crate::source::SeekError;
5use crate::Source;
6
7use hound::{SampleFormat, WavReader};
8
9pub struct WavDecoder<R>
11where
12 R: Read + Seek,
13{
14 reader: SamplesIterator<R>,
15 total_duration: Duration,
16 sample_rate: u32,
17 channels: u16,
18}
19
20impl<R> WavDecoder<R>
21where
22 R: Read + Seek,
23{
24 pub fn new(mut data: R) -> Result<WavDecoder<R>, R> {
26 if !is_wave(data.by_ref()) {
27 return Err(data);
28 }
29
30 let reader = WavReader::new(data).unwrap();
31 let spec = reader.spec();
32 let len = reader.len() as u64;
33 let reader = SamplesIterator {
34 reader,
35 samples_read: 0,
36 };
37
38 let sample_rate = spec.sample_rate;
39 let channels = spec.channels;
40 let total_duration =
41 Duration::from_micros((1_000_000 * len) / (sample_rate as u64 * channels as u64));
42
43 Ok(WavDecoder {
44 reader,
45 total_duration,
46 sample_rate,
47 channels,
48 })
49 }
50 pub fn into_inner(self) -> R {
51 self.reader.reader.into_inner()
52 }
53}
54
55struct SamplesIterator<R>
56where
57 R: Read + Seek,
58{
59 reader: WavReader<R>,
60 samples_read: u32, }
62
63impl<R> Iterator for SamplesIterator<R>
64where
65 R: Read + Seek,
66{
67 type Item = i16;
68
69 #[inline]
70 fn next(&mut self) -> Option<i16> {
71 let spec = self.reader.spec();
72 match (spec.sample_format, spec.bits_per_sample) {
73 (SampleFormat::Float, 32) => self.reader.samples().next().map(|value| {
74 self.samples_read += 1;
75 f32_to_i16(value.unwrap_or(0.0))
76 }),
77 (SampleFormat::Int, 8) => self.reader.samples().next().map(|value| {
78 self.samples_read += 1;
79 i8_to_i16(value.unwrap_or(0))
80 }),
81 (SampleFormat::Int, 16) => self.reader.samples().next().map(|value| {
82 self.samples_read += 1;
83 value.unwrap_or(0)
84 }),
85 (SampleFormat::Int, 24) => self.reader.samples().next().map(|value| {
86 self.samples_read += 1;
87 i24_to_i16(value.unwrap_or(0))
88 }),
89 (SampleFormat::Int, 32) => self.reader.samples().next().map(|value| {
90 self.samples_read += 1;
91 i32_to_i16(value.unwrap_or(0))
92 }),
93 (sample_format, bits_per_sample) => {
94 panic!("Unimplemented wav spec: {sample_format:?}, {bits_per_sample}")
95 }
96 }
97 }
98
99 #[inline]
100 fn size_hint(&self) -> (usize, Option<usize>) {
101 let len = (self.reader.len() - self.samples_read) as usize;
102 (len, Some(len))
103 }
104}
105
106impl<R> ExactSizeIterator for SamplesIterator<R> where R: Read + Seek {}
107
108impl<R> Source for WavDecoder<R>
109where
110 R: Read + Seek,
111{
112 #[inline]
113 fn current_frame_len(&self) -> Option<usize> {
114 None
115 }
116
117 #[inline]
118 fn channels(&self) -> u16 {
119 self.channels
120 }
121
122 #[inline]
123 fn sample_rate(&self) -> u32 {
124 self.sample_rate
125 }
126
127 #[inline]
128 fn total_duration(&self) -> Option<Duration> {
129 Some(self.total_duration)
130 }
131
132 #[inline]
133 fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
134 let file_len = self.reader.reader.duration();
135
136 let new_pos = pos.as_secs_f32() * self.sample_rate() as f32;
137 let new_pos = new_pos as u32;
138 let new_pos = new_pos.min(file_len); let to_skip = self.reader.samples_read % self.channels() as u32;
142
143 self.reader
144 .reader
145 .seek(new_pos)
146 .map_err(SeekError::HoundDecoder)?;
147 self.reader.samples_read = new_pos * self.channels() as u32;
148
149 for _ in 0..to_skip {
150 self.next();
151 }
152
153 Ok(())
154 }
155}
156
157impl<R> Iterator for WavDecoder<R>
158where
159 R: Read + Seek,
160{
161 type Item = i16;
162
163 #[inline]
164 fn next(&mut self) -> Option<i16> {
165 self.reader.next()
166 }
167
168 #[inline]
169 fn size_hint(&self) -> (usize, Option<usize>) {
170 self.reader.size_hint()
171 }
172}
173
174impl<R> ExactSizeIterator for WavDecoder<R> where R: Read + Seek {}
175
176fn is_wave<R>(mut data: R) -> bool
178where
179 R: Read + Seek,
180{
181 let stream_pos = data.stream_position().unwrap();
182
183 if WavReader::new(data.by_ref()).is_err() {
184 data.seek(SeekFrom::Start(stream_pos)).unwrap();
185 return false;
186 }
187
188 data.seek(SeekFrom::Start(stream_pos)).unwrap();
189 true
190}
191
192fn f32_to_i16(f: f32) -> i16 {
197 (f.clamp(-1.0, 1.0) * i16::MAX as f32) as i16
199}
200
201fn i8_to_i16(i: i8) -> i16 {
204 i as i16 * 256
205}
206
207fn i24_to_i16(i: i32) -> i16 {
212 (i >> 8) as i16
213}
214
215fn i32_to_i16(i: i32) -> i16 {
220 (i >> 16) as i16
221}