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
9/// Decoder for the WAV format.
10pub 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    /// Attempts to decode the data as WAV.
25    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, // wav header is u32 so this suffices
61}
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); // saturate pos at the end of the source
139
140        // make sure the next sample is for the right channel
141        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
176/// Returns true if the stream contains WAV data, then resets it to where it was.
177fn 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
192/// Returns a 32 bit WAV float as an i16. WAV floats are typically in the range of
193/// [-1.0, 1.0] while i16s are in the range [-32768, 32767]. Note that this
194/// function definitely causes precision loss but hopefully this isn't too
195/// audiable when actually playing?
196fn f32_to_i16(f: f32) -> i16 {
197    // prefer to clip the input rather than be excessively loud.
198    (f.clamp(-1.0, 1.0) * i16::MAX as f32) as i16
199}
200
201/// Returns an 8-bit WAV int as an i16. This scales the sample value by a factor
202/// of 256.
203fn i8_to_i16(i: i8) -> i16 {
204    i as i16 * 256
205}
206
207/// Returns a 24 bit WAV int as an i16. Note that this is a 24 bit integer, not a
208/// 32 bit one. 24 bit ints are in the range [−8,388,608, 8,388,607] while i16s
209/// are in the range [-32768, 32767]. Note that this function definitely causes
210/// precision loss but hopefully this isn't too audiable when actually playing?
211fn i24_to_i16(i: i32) -> i16 {
212    (i >> 8) as i16
213}
214
215/// Returns a 32 bit WAV int as an i16. 32 bit ints are in the range
216/// [-2,147,483,648, 2,147,483,647] while i16s are in the range [-32768, 32767].
217/// Note that this function definitely causes precision loss but hopefully this
218/// isn't too audiable when actually playing?
219fn i32_to_i16(i: i32) -> i16 {
220    (i >> 16) as i16
221}