1 // Hound -- A wav encoding and decoding library in Rust
2 // Copyright (C) 2015 Ruud van Asseldonk
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // A copy of the License has been included in the root of the repository.
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 use std::cmp;
14 use std::fs;
15 use std::io;
16 use std::marker;
17 use std::mem;
18 use std::path;
19 use super::{Error, Result, Sample, SampleFormat, WavSpec};
20 
21 /// Extends the functionality of `io::Read` with additional methods.
22 ///
23 /// The methods may be used on any type that implements `io::Read`.
24 pub trait ReadExt: io::Read {
25     /// Reads as many bytes as `buf` is long.
26     ///
27     /// This may issue multiple `read` calls internally. An error is returned
28     /// if `read` read 0 bytes before the buffer is full.
29     //  TODO: There is an RFC proposing a method like this for the standard library.
read_into(&mut self, buf: &mut [u8]) -> io::Result<()>30     fn read_into(&mut self, buf: &mut [u8]) -> io::Result<()>;
31 
32     /// Reads `n` bytes and returns them in a vector.
read_bytes(&mut self, n: usize) -> io::Result<Vec<u8>>33     fn read_bytes(&mut self, n: usize) -> io::Result<Vec<u8>>;
34 
35     /// Skip over `n` bytes.
skip_bytes(&mut self, n: usize) -> io::Result<()>36     fn skip_bytes(&mut self, n: usize) -> io::Result<()>;
37 
38     /// Reads a single byte and interprets it as an 8-bit signed integer.
read_i8(&mut self) -> io::Result<i8>39     fn read_i8(&mut self) -> io::Result<i8>;
40 
41     /// Reads a single byte and interprets it as an 8-bit unsigned integer.
read_u8(&mut self) -> io::Result<u8>42     fn read_u8(&mut self) -> io::Result<u8>;
43 
44     /// Reads two bytes and interprets them as a little-endian 16-bit signed integer.
read_le_i16(&mut self) -> io::Result<i16>45     fn read_le_i16(&mut self) -> io::Result<i16>;
46 
47     /// Reads two bytes and interprets them as a little-endian 16-bit unsigned integer.
read_le_u16(&mut self) -> io::Result<u16>48     fn read_le_u16(&mut self) -> io::Result<u16>;
49 
50     /// Reads three bytes and interprets them as a little-endian 24-bit signed integer.
51     ///
52     /// The sign bit will be extended into the most significant byte.
read_le_i24(&mut self) -> io::Result<i32>53     fn read_le_i24(&mut self) -> io::Result<i32>;
54 
55     /// Reads three bytes and interprets them as a little-endian 24-bit unsigned integer.
56     ///
57     /// The most significant byte will be 0.
read_le_u24(&mut self) -> io::Result<u32>58     fn read_le_u24(&mut self) -> io::Result<u32>;
59 
60     /// Reads four bytes and interprets them as a little-endian 32-bit signed integer.
read_le_i32(&mut self) -> io::Result<i32>61     fn read_le_i32(&mut self) -> io::Result<i32>;
62 
63     /// Reads four bytes and interprets them as a little-endian 32-bit unsigned integer.
read_le_u32(&mut self) -> io::Result<u32>64     fn read_le_u32(&mut self) -> io::Result<u32>;
65 
66     /// Reads four bytes and interprets them as a little-endian 32-bit IEEE float.
read_le_f32(&mut self) -> io::Result<f32>67     fn read_le_f32(&mut self) -> io::Result<f32>;
68 }
69 
70 impl<R> ReadExt for R
71     where R: io::Read
72 {
73     #[inline(always)]
read_into(&mut self, buf: &mut [u8]) -> io::Result<()>74     fn read_into(&mut self, buf: &mut [u8]) -> io::Result<()> {
75         let mut n = 0;
76         while n < buf.len() {
77             let progress = try!(self.read(&mut buf[n..]));
78             if progress > 0 {
79                 n += progress;
80             } else {
81                 return Err(io::Error::new(io::ErrorKind::Other, "Failed to read enough bytes."));
82             }
83         }
84         Ok(())
85     }
86 
87     #[inline(always)]
skip_bytes(&mut self, n: usize) -> io::Result<()>88     fn skip_bytes(&mut self, n: usize) -> io::Result<()> {
89         // Read from the input in chunks of 1024 bytes at a time, and discard
90         // the result. 1024 is a tradeoff between doing a lot of calls, and
91         // using too much stack space. This method is not in a hot path, so it
92         // can afford to do this.
93         let mut n_read = 0;
94         let mut buf = [0u8; 1024];
95         while n_read < n {
96             let end = cmp::min(n - n_read, 1024);
97             let progress = try!(self.read(&mut buf[0..end]));
98             if progress > 0 {
99                 n_read += progress;
100             } else {
101                 return Err(io::Error::new(io::ErrorKind::Other, "Failed to read enough bytes."));
102             }
103         }
104         Ok(())
105     }
106 
107     #[inline(always)]
read_bytes(&mut self, n: usize) -> io::Result<Vec<u8>>108     fn read_bytes(&mut self, n: usize) -> io::Result<Vec<u8>> {
109         // We allocate a runtime fixed size buffer, and we are going to read
110         // into it, so zeroing or filling the buffer is a waste. This method
111         // is safe, because the contents of the buffer are only exposed when
112         // they have been overwritten completely by the read.
113         let mut buf = Vec::with_capacity(n);
114         unsafe { buf.set_len(n); }
115         try!(self.read_into(&mut buf[..]));
116         Ok(buf)
117     }
118 
119     #[inline(always)]
read_i8(&mut self) -> io::Result<i8>120     fn read_i8(&mut self) -> io::Result<i8> {
121         self.read_u8().map(|x| x as i8)
122     }
123 
124     #[inline(always)]
read_u8(&mut self) -> io::Result<u8>125     fn read_u8(&mut self) -> io::Result<u8> {
126         let mut buf = [0u8; 1];
127         try!(self.read_into(&mut buf));
128         Ok(buf[0])
129     }
130 
131     #[inline(always)]
read_le_i16(&mut self) -> io::Result<i16>132     fn read_le_i16(&mut self) -> io::Result<i16> {
133         self.read_le_u16().map(|x| x as i16)
134     }
135 
136     #[inline(always)]
read_le_u16(&mut self) -> io::Result<u16>137     fn read_le_u16(&mut self) -> io::Result<u16> {
138         let mut buf = [0u8; 2];
139         try!(self.read_into(&mut buf));
140         Ok((buf[1] as u16) << 8 | (buf[0] as u16))
141     }
142 
143     #[inline(always)]
read_le_i24(&mut self) -> io::Result<i32>144     fn read_le_i24(&mut self) -> io::Result<i32> {
145         self.read_le_u24().map(|x|
146             // Test the sign bit, if it is set, extend the sign bit into the
147             // most significant byte.
148             if x & (1 << 23) == 0 {
149                 x as i32
150             } else {
151                 (x | 0xff_00_00_00) as i32
152             }
153         )
154     }
155 
156     #[inline(always)]
read_le_u24(&mut self) -> io::Result<u32>157     fn read_le_u24(&mut self) -> io::Result<u32> {
158         let mut buf = [0u8; 3];
159         try!(self.read_into(&mut buf));
160         Ok((buf[2] as u32) << 16 | (buf[1] as u32) << 8 | (buf[0] as u32))
161     }
162 
163     #[inline(always)]
read_le_i32(&mut self) -> io::Result<i32>164     fn read_le_i32(&mut self) -> io::Result<i32> {
165         self.read_le_u32().map(|x| x as i32)
166     }
167 
168     #[inline(always)]
read_le_u32(&mut self) -> io::Result<u32>169     fn read_le_u32(&mut self) -> io::Result<u32> {
170         let mut buf = [0u8; 4];
171         try!(self.read_into(&mut buf));
172         Ok((buf[3] as u32) << 24 | (buf[2] as u32) << 16 |
173            (buf[1] as u32) << 8  | (buf[0] as u32) << 0)
174     }
175 
176     #[inline(always)]
read_le_f32(&mut self) -> io::Result<f32>177     fn read_le_f32(&mut self) -> io::Result<f32> {
178         self.read_le_u32().map(|u| unsafe { mem::transmute(u) })
179     }
180 }
181 
182 /// The different chunks that a WAVE file can contain.
183 enum ChunkKind {
184     Fmt,
185     Fact,
186     Data,
187     Unknown,
188 }
189 
190 /// Describes the structure of a chunk in the WAVE file.
191 struct ChunkHeader {
192     pub kind: ChunkKind,
193     pub len: u32,
194 }
195 
196 /// Specifies properties of the audio data, as well as the layout of the stream.
197 #[derive(Clone, Copy)]
198 pub struct WavSpecEx {
199     /// The normal information about the audio data.
200     ///
201     /// Bits per sample here is the number of _used_ bits per sample, not the
202     /// number of bits used to _store_ a sample.
203     pub spec: WavSpec,
204 
205     /// The number of bytes used to store a sample.
206     pub bytes_per_sample: u16,
207 }
208 
209 /// A reader that reads the WAVE format from the underlying reader.
210 ///
211 /// A `WavReader` is a streaming reader. It reads data from the underlying
212 /// reader on demand, and it reads no more than strictly necessary. No internal
213 /// buffering is performed on the underlying reader, but this can easily be
214 /// added by wrapping the reader in an `io::BufReader`. The `open` constructor
215 /// takes care of this for you.
216 pub struct WavReader<R> {
217     /// Specification of the file as found in the fmt chunk.
218     spec: WavSpec,
219 
220     /// The number of bytes used to store a sample in the stream.
221     bytes_per_sample: u16,
222 
223     /// The number of samples in the data chunk.
224     ///
225     /// The data chunk is limited to a 4 GiB length because its header has a
226     /// 32-bit length field. A sample takes at least one byte to store, so the
227     /// number of samples is always less than 2^32.
228     num_samples: u32,
229 
230     /// The number of samples read so far.
231     samples_read: u32,
232 
233     /// The reader from which the WAVE format is read.
234     reader: R,
235 }
236 
237 /// An iterator that yields samples of type `S` read from a `WavReader`.
238 ///
239 /// The type `S` must have at least as many bits as the bits per sample of the
240 /// file, otherwise every iteration will return an error.
241 pub struct WavSamples<'wr, R, S>
242     where R: 'wr
243 {
244     reader: &'wr mut WavReader<R>,
245     phantom_sample: marker::PhantomData<S>,
246 }
247 
248 /// An iterator that yields samples of type `S` read from a `WavReader`.
249 ///
250 /// The type `S` must have at least as many bits as the bits per sample of the
251 /// file, otherwise every iteration will return an error.
252 pub struct WavIntoSamples<R, S> {
253     reader: WavReader<R>,
254     phantom_sample: marker::PhantomData<S>,
255 }
256 
257 /// Reads the RIFF WAVE header, returns the supposed file size.
258 ///
259 /// This function can be used to quickly check if the file could be a wav file
260 /// by reading 12 bytes of the header. If an `Ok` is returned, the file is
261 /// likely a wav file. If an `Err` is returned, it is definitely not a wav
262 /// file.
263 ///
264 /// The returned file size cannot be larger than 2<sup>32</sup> + 7 bytes.
read_wave_header<R: io::Read>(reader: &mut R) -> Result<u64>265 pub fn read_wave_header<R: io::Read>(reader: &mut R) -> Result<u64> {
266     // Every WAVE file starts with the four bytes 'RIFF' and a file length.
267     // TODO: the old approach of having a slice on the stack and reading
268     // into it is more cumbersome, but also avoids a heap allocation. Is
269     // the compiler smart enough to avoid the heap allocation anyway? I
270     // would not expect it to be.
271     if b"RIFF" != &try!(reader.read_bytes(4))[..] {
272         return Err(Error::FormatError("no RIFF tag found"));
273     }
274 
275     let file_len = try!(reader.read_le_u32());
276 
277     // Next four bytes indicate the file type, which should be WAVE.
278     if b"WAVE" != &try!(reader.read_bytes(4))[..] {
279         return Err(Error::FormatError("no WAVE tag found"));
280     }
281 
282     // The stored file length does not include the "RIFF" magic and 4-byte
283     // length field, so the total size is 8 bytes more than what is stored.
284     Ok(file_len as u64 + 8)
285 }
286 
287 /// Reads chunks until a data chunk is encountered.
288 ///
289 /// Returns the information from the fmt chunk and the length of the data
290 /// chunk in bytes. Afterwards, the reader will be positioned at the first
291 /// content byte of the data chunk.
read_until_data<R: io::Read>(mut reader: R) -> Result<(WavSpecEx, u32)>292 pub fn read_until_data<R: io::Read>(mut reader: R) -> Result<(WavSpecEx, u32)> {
293     let mut spec_opt = None;
294 
295     loop {
296         let header = try!(WavReader::read_chunk_header(&mut reader));
297         match header.kind {
298             ChunkKind::Fmt => {
299                 let spec = try!(WavReader::read_fmt_chunk(&mut reader, header.len));
300                 spec_opt = Some(spec);
301             }
302             ChunkKind::Fact => {
303                 // All (compressed) non-PCM formats must have a fact chunk
304                 // (Rev. 3 documentation). The chunk contains at least one
305                 // value, the number of samples in the file.
306                 //
307                 // The number of samples field is redundant for sampled
308                 // data, since the Data chunk indicates the length of the
309                 // data. The number of samples can be determined from the
310                 // length of the data and the container size as determined
311                 // from the Format chunk.
312                 // http://www-mmsp.ece.mcgill.ca/documents/audioformats/wave/wave.html
313                 let _samples_per_channel = reader.read_le_u32();
314             }
315             ChunkKind::Data => {
316                 // The "fmt" chunk must precede the "data" chunk. Any
317                 // chunks that come after the data chunk will be ignored.
318                 if let Some(spec) = spec_opt {
319                     return Ok((spec, header.len));
320                 } else {
321                     return Err(Error::FormatError("missing fmt chunk"));
322                 }
323             }
324             ChunkKind::Unknown => {
325                 // Ignore the chunk; skip all of its bytes.
326                 try!(reader.skip_bytes(header.len as usize));
327             }
328         }
329         // If no data chunk is ever encountered, the function will return
330         // via one of the try! macros that return an Err on end of file.
331     }
332 }
333 
334 impl<R> WavReader<R>
335     where R: io::Read
336 {
337     /// Attempts to read an 8-byte chunk header.
read_chunk_header(reader: &mut R) -> Result<ChunkHeader>338     fn read_chunk_header(reader: &mut R) -> Result<ChunkHeader> {
339         let mut kind_str = [0; 4];
340         try!(reader.read_into(&mut kind_str));
341         let len = try!(reader.read_le_u32());
342 
343         let kind = match &kind_str[..] {
344             b"fmt " => ChunkKind::Fmt,
345             b"fact" => ChunkKind::Fact,
346             b"data" => ChunkKind::Data,
347             _ => ChunkKind::Unknown,
348         };
349 
350         Ok(ChunkHeader { kind: kind, len: len })
351     }
352 
353     /// Reads the fmt chunk of the file, returns the information it provides.
read_fmt_chunk(reader: &mut R, chunk_len: u32) -> Result<WavSpecEx>354     fn read_fmt_chunk(reader: &mut R, chunk_len: u32) -> Result<WavSpecEx> {
355         // A minimum chunk length of at least 16 is assumed. Note: actually,
356         // the first 14 bytes contain enough information to fully specify the
357         // file. I have not encountered a file with a 14-byte fmt section
358         // though. If you ever encounter such file, please contact me.
359         if chunk_len < 16 {
360             return Err(Error::FormatError("invalid fmt chunk size"));
361         }
362 
363         // Read the WAVEFORMAT struct, as defined at
364         // https://msdn.microsoft.com/en-us/library/ms713498.aspx.
365         // ```
366         // typedef struct {
367         //     WORD  wFormatTag;
368         //     WORD  nChannels;
369         //     DWORD nSamplesPerSec;
370         //     DWORD nAvgBytesPerSec;
371         //     WORD  nBlockAlign;
372         // } WAVEFORMAT;
373         // ```
374         // The WAVEFORMATEX struct has two more members, as defined at
375         // https://msdn.microsoft.com/en-us/library/ms713497.aspx
376         // ```
377         // typedef struct {
378         //     WORD  wFormatTag;
379         //     WORD  nChannels;
380         //     DWORD nSamplesPerSec;
381         //     DWORD nAvgBytesPerSec;
382         //     WORD  nBlockAlign;
383         //     WORD  wBitsPerSample;
384         //     WORD  cbSize;
385         // } WAVEFORMATEX;
386         // ```
387         // There is also PCMWAVEFORMAT as defined at
388         // https://msdn.microsoft.com/en-us/library/dd743663.aspx.
389         // ```
390         // typedef struct {
391         //   WAVEFORMAT wf;
392         //   WORD       wBitsPerSample;
393         // } PCMWAVEFORMAT;
394         // ```
395         // In either case, the minimal length of the fmt section is 16 bytes,
396         // meaning that it does include the `wBitsPerSample` field. (The name
397         // is misleading though, because it is the number of bits used to store
398         // a sample, not all of the bits need to be valid for all versions of
399         // the WAVE format.)
400         let format_tag = try!(reader.read_le_u16());
401         let n_channels = try!(reader.read_le_u16());
402         let n_samples_per_sec = try!(reader.read_le_u32());
403         let n_bytes_per_sec = try!(reader.read_le_u32());
404         let block_align = try!(reader.read_le_u16());
405         let bits_per_sample = try!(reader.read_le_u16());
406 
407         if n_channels == 0 {
408             return Err(Error::FormatError("file contains zero channels"));
409         }
410 
411         // Two of the stored fields are redundant, and may be ignored. We do
412         // validate them to fail early for ill-formed files.
413         if (Some(bits_per_sample) != (block_align / n_channels).checked_mul(8)) ||
414            (Some(n_bytes_per_sec) != (block_align as u32).checked_mul(n_samples_per_sec)) {
415             return Err(Error::FormatError("inconsistent fmt chunk"));
416         }
417 
418         // The bits per sample for a WAVEFORMAT struct is the number of bits
419         // used to store a sample. Therefore, it must be a multiple of 8.
420         if bits_per_sample % 8 != 0 {
421             return Err(Error::FormatError("bits per sample is not a multiple of 8"));
422         }
423 
424         if bits_per_sample == 0 {
425             return Err(Error::FormatError("bits per sample is 0"));
426         }
427 
428         let spec = WavSpec {
429             channels: n_channels,
430             sample_rate: n_samples_per_sec,
431             bits_per_sample: bits_per_sample,
432             sample_format: SampleFormat::Int,
433         };
434 
435         // The different format tag definitions can be found in mmreg.h that is
436         // part of the Windows SDK. The vast majority are esoteric vendor-
437         // specific formats. We handle only a few. The following values could
438         // be of interest:
439         const PCM: u16 = 0x0001;
440         const ADPCM: u16 = 0x0002;
441         const IEEE_FLOAT: u16 = 0x0003;
442         const EXTENSIBLE: u16 = 0xfffe;
443         match format_tag {
444             PCM => WavReader::read_wave_format_pcm(reader, chunk_len, spec),
445             ADPCM => Err(Error::Unsupported),
446             IEEE_FLOAT => WavReader::read_wave_format_ieee_float(reader, chunk_len, spec),
447             EXTENSIBLE => WavReader::read_wave_format_extensible(reader, chunk_len, spec),
448             _ => Err(Error::Unsupported),
449         }
450     }
451 
read_wave_format_pcm(mut reader: R, chunk_len: u32, spec: WavSpec) -> Result<WavSpecEx>452     fn read_wave_format_pcm(mut reader: R, chunk_len: u32, spec: WavSpec) -> Result<WavSpecEx> {
453         // When there is a PCMWAVEFORMAT struct, the chunk is 16 bytes long.
454         // The WAVEFORMATEX structs includes two extra bytes, `cbSize`.
455         let is_wave_format_ex = match chunk_len {
456             16 => false,
457             18 => true,
458             // Other sizes are unexpected, but such files do occur in the wild,
459             // and reading these files is still possible, so we allow this.
460             40 => true,
461             _ => return Err(Error::FormatError("unexpected fmt chunk size")),
462         };
463 
464         if is_wave_format_ex {
465             // `cbSize` can be used for non-PCM formats to specify the size of
466             // additional data. However, for WAVE_FORMAT_PCM, the member should
467             // be ignored, see https://msdn.microsoft.com/en-us/library/ms713497.aspx.
468             // Nonzero values do in fact occur in practice.
469             let _cb_size = try!(reader.read_le_u16());
470 
471             // For WAVE_FORMAT_PCM in WAVEFORMATEX, only 8 or 16 bits per
472             // sample are valid according to
473             // https://msdn.microsoft.com/en-us/library/ms713497.aspx.
474             // 24 bits per sample is explicitly not valid inside a WAVEFORMATEX
475             // structure, but such files do occur in the wild nonetheless, and
476             // there is no good reason why we couldn't read them.
477             match spec.bits_per_sample {
478                 8 => {}
479                 16 => {}
480                 24 => {}
481                 _ => return Err(Error::FormatError("bits per sample is not 8 or 16")),
482             }
483         }
484 
485         // If the chunk len was longer than expected, ignore the additional bytes.
486         if chunk_len == 40 {
487             try!(reader.skip_bytes(22));
488         }
489 
490         let spec_ex = WavSpecEx {
491             spec: spec,
492             bytes_per_sample: spec.bits_per_sample / 8,
493         };
494         Ok(spec_ex)
495     }
496 
read_wave_format_ieee_float(mut reader: R, chunk_len: u32, spec: WavSpec) -> Result<WavSpecEx>497     fn read_wave_format_ieee_float(mut reader: R, chunk_len: u32, spec: WavSpec)
498                                    -> Result<WavSpecEx> {
499         // When there is a PCMWAVEFORMAT struct, the chunk is 16 bytes long.
500         // The WAVEFORMATEX structs includes two extra bytes, `cbSize`.
501         let is_wave_format_ex = chunk_len == 18;
502 
503         if !is_wave_format_ex && chunk_len != 16 {
504             return Err(Error::FormatError("unexpected fmt chunk size"));
505         }
506 
507         if is_wave_format_ex {
508             // For WAVE_FORMAT_IEEE_FLOAT which we are reading, there should
509             // be no extra data, so `cbSize` should be 0.
510             let cb_size = try!(reader.read_le_u16());
511             if cb_size != 0 {
512                 return Err(Error::FormatError("unexpected WAVEFORMATEX size"));
513             }
514         }
515 
516         // For WAVE_FORMAT_IEEE_FLOAT, the bits_per_sample field should be
517         // set to `32` according to
518         // https://msdn.microsoft.com/en-us/library/windows/hardware/ff538799(v=vs.85).aspx.
519         //
520         // Note that some applications support 64 bits per sample. This is
521         // not yet supported by hound.
522         if spec.bits_per_sample != 32 {
523             return Err(Error::FormatError("bits per sample is not 32"));
524         }
525 
526         let spec_ex = WavSpecEx {
527             spec: WavSpec {
528                 sample_format: SampleFormat::Float,
529                 ..spec
530             },
531             bytes_per_sample: spec.bits_per_sample / 8,
532         };
533         Ok(spec_ex)
534     }
535 
read_wave_format_extensible(mut reader: R, chunk_len: u32, spec: WavSpec) -> Result<WavSpecEx>536     fn read_wave_format_extensible(mut reader: R, chunk_len: u32, spec: WavSpec)
537                                    -> Result<WavSpecEx> {
538         // 16 bytes were read already, there must be two more for the `cbSize`
539         // field, and `cbSize` itself must be at least 22, so the chunk length
540         // must be at least 40.
541         if chunk_len < 40 {
542             return Err(Error::FormatError("unexpected fmt chunk size"));
543         }
544 
545         // `cbSize` is the last field of the WAVEFORMATEX struct.
546         let cb_size = try!(reader.read_le_u16());
547 
548         // `cbSize` must be at least 22, but in this case we assume that it is
549         // 22, because we would not know how to handle extra data anyway.
550         if cb_size != 22 {
551             return Err(Error::FormatError("unexpected WAVEFORMATEXTENSIBLE size"));
552         }
553 
554         // What follows is the rest of the `WAVEFORMATEXTENSIBLE` struct, as
555         // defined at https://msdn.microsoft.com/en-us/library/ms713496.aspx.
556         // ```
557         // typedef struct {
558         //   WAVEFORMATEX  Format;
559         //   union {
560         //     WORD  wValidBitsPerSample;
561         //     WORD  wSamplesPerBlock;
562         //     WORD  wReserved;
563         //   } Samples;
564         //   DWORD   dwChannelMask;
565         //   GUID    SubFormat;
566         // } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
567         // ```
568         let valid_bits_per_sample = try!(reader.read_le_u16());
569         let _channel_mask = try!(reader.read_le_u32()); // Not used for now.
570         let mut subformat = [0u8; 16];
571         try!(reader.read_into(&mut subformat));
572 
573         // Several GUIDS are defined. At the moment, only the following are supported:
574         //
575         // * KSDATAFORMAT_SUBTYPE_PCM (PCM audio with integer samples).
576         // * KSDATAFORMAT_SUBTYPE_IEEE_FLOAT (PCM audio with floating point samples).
577         let sample_format = match subformat {
578             super::KSDATAFORMAT_SUBTYPE_PCM => SampleFormat::Int,
579             super::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT => SampleFormat::Float,
580             _ => return Err(Error::Unsupported),
581         };
582 
583         let spec_ex = WavSpecEx {
584             spec: WavSpec {
585                 bits_per_sample: valid_bits_per_sample,
586                 sample_format: sample_format,
587                 ..spec
588             },
589             bytes_per_sample: spec.bits_per_sample / 8,
590         };
591         Ok(spec_ex)
592     }
593 
594     /// Attempts to create a reader that reads the WAVE format.
595     ///
596     /// The header is read immediately. Reading the data will be done on
597     /// demand.
new(mut reader: R) -> Result<WavReader<R>>598     pub fn new(mut reader: R) -> Result<WavReader<R>> {
599         try!(read_wave_header(&mut reader));
600         let (spec_ex, data_len) = try!(read_until_data(&mut reader));
601 
602         let num_samples = data_len / spec_ex.bytes_per_sample as u32;
603 
604         // It could be that num_samples * bytes_per_sample < data_len.
605         // If data_len is not a multiple of bytes_per_sample, there is some
606         // trailing data. Either somebody is playing some steganography game,
607         // but more likely something is very wrong, and we should refuse to
608         // decode the file, as it is invalid.
609         if num_samples * spec_ex.bytes_per_sample as u32 != data_len {
610             let msg = "data chunk length is not a multiple of sample size";
611             return Err(Error::FormatError(msg));
612         }
613 
614         // The number of samples must be a multiple of the number of channels,
615         // otherwise the last inter-channel sample would not have data for all
616         // channels.
617         if num_samples % spec_ex.spec.channels as u32 != 0 {
618             return Err(Error::FormatError("invalid data chunk length"));
619         }
620 
621         let wav_reader = WavReader {
622             spec: spec_ex.spec,
623             bytes_per_sample: spec_ex.bytes_per_sample,
624             num_samples: num_samples,
625             samples_read: 0,
626             reader: reader,
627         };
628 
629         Ok(wav_reader)
630     }
631 
632     /// Returns information about the WAVE file.
spec(&self) -> WavSpec633     pub fn spec(&self) -> WavSpec {
634         self.spec
635     }
636 
637     /// Returns an iterator over all samples.
638     ///
639     /// The channel data is is interleaved. The iterator is streaming. That is,
640     /// if you call this method once, read a few samples, and call this method
641     /// again, the second iterator will not start again from the beginning of
642     /// the file, it will continue where the first iterator stopped.
643     ///
644     /// The type `S` must have at least `spec().bits_per_sample` bits,
645     /// otherwise every iteration will return an error. All bit depths up to
646     /// 32 bits per sample can be decoded into an `i32`, but if you know
647     /// beforehand that you will be reading a file with 16 bits per sample, you
648     /// can save memory by decoding into an `i16`.
649     ///
650     /// The type of `S` (int or float) must match `spec().sample_format`,
651     /// otherwise every iteration will return an error.
samples<'wr, S: Sample>(&'wr mut self) -> WavSamples<'wr, R, S>652     pub fn samples<'wr, S: Sample>(&'wr mut self) -> WavSamples<'wr, R, S> {
653         WavSamples {
654             reader: self,
655             phantom_sample: marker::PhantomData,
656         }
657     }
658 
659     /// Same as `samples`, but takes ownership of the `WavReader`.
660     ///
661     /// See `samples()` for more info.
into_samples<S: Sample>(self) -> WavIntoSamples<R, S>662     pub fn into_samples<S: Sample>(self) -> WavIntoSamples<R, S> {
663         WavIntoSamples {
664             reader: self,
665             phantom_sample: marker::PhantomData,
666         }
667     }
668 
669     /// Returns the duration of the file in samples.
670     ///
671     /// The duration is independent of the number of channels. It is expressed
672     /// in units of samples. The duration in seconds can be obtained by
673     /// dividing this number by the sample rate. The duration is independent of
674     /// how many samples have been read already.
duration(&self) -> u32675     pub fn duration(&self) -> u32 {
676         self.num_samples / self.spec.channels as u32
677     }
678 
679     /// Returns the number of values that the sample iterator will yield.
680     ///
681     /// The length of the file is its duration (in samples) times the number of
682     /// channels. The length is independent of how many samples have been read
683     /// already. To get the number of samples left, use `len()` on the
684     /// `samples()` iterator.
len(&self) -> u32685     pub fn len(&self) -> u32 {
686         self.num_samples
687     }
688 
689     /// Destroys the `WavReader` and returns the underlying reader.
into_inner(self) -> R690     pub fn into_inner(self) -> R {
691         self.reader
692     }
693 
694     /// Seek to the given time within the file.
695     ///
696     /// The given time is measured in number of samples (independent of the
697     /// number of channels) since the beginning of the audio data. To seek to
698     /// a particular time in seconds, multiply the number of seconds with
699     /// `WavSpec::sample_rate`. The given time should not exceed the duration of
700     /// the file (returned by `duration()`). The behavior when seeking beyond
701     /// `duration()` depends on the reader's `Seek` implementation.
702     ///
703     /// This method requires that the inner reader `R` implements `Seek`.
seek(&mut self, time: u32) -> io::Result<()> where R: io::Seek,704     pub fn seek(&mut self, time: u32) -> io::Result<()>
705         where R: io::Seek,
706     {
707         let bytes_per_sample = self.spec.bits_per_sample / 8;
708         let sample_position = time * self.spec.channels as u32;
709         let offset_samples = sample_position as i64 - self.samples_read as i64;
710         let offset_bytes = offset_samples * bytes_per_sample as i64;
711         try!(self.reader.seek(io::SeekFrom::Current(offset_bytes)));
712         self.samples_read = sample_position;
713         Ok(())
714     }
715 }
716 
717 impl WavReader<io::BufReader<fs::File>> {
718     /// Attempts to create a reader that reads from the specified file.
719     ///
720     /// This is a convenience constructor that opens a `File`, wraps it in a
721     /// `BufReader` and then constructs a `WavReader` from it.
open<P: AsRef<path::Path>>(filename: P) -> Result<WavReader<io::BufReader<fs::File>>>722     pub fn open<P: AsRef<path::Path>>(filename: P) -> Result<WavReader<io::BufReader<fs::File>>> {
723         let file = try!(fs::File::open(filename));
724         let buf_reader = io::BufReader::new(file);
725         WavReader::new(buf_reader)
726     }
727 }
728 
iter_next<R, S>(reader: &mut WavReader<R>) -> Option<Result<S>> where R: io::Read, S: Sample729 fn iter_next<R, S>(reader: &mut WavReader<R>) -> Option<Result<S>>
730     where R: io::Read,
731           S: Sample
732 {
733     if reader.samples_read < reader.num_samples {
734         reader.samples_read += 1;
735         let sample = Sample::read(&mut reader.reader,
736                                   reader.spec.sample_format,
737                                   reader.bytes_per_sample,
738                                   reader.spec.bits_per_sample);
739         Some(sample.map_err(Error::from))
740     } else {
741         None
742     }
743 }
744 
iter_size_hint<R>(reader: &WavReader<R>) -> (usize, Option<usize>)745 fn iter_size_hint<R>(reader: &WavReader<R>) -> (usize, Option<usize>) {
746     let samples_left = reader.num_samples - reader.samples_read;
747     (samples_left as usize, Some(samples_left as usize))
748 }
749 
750 impl<'wr, R, S> Iterator for WavSamples<'wr, R, S>
751     where R: io::Read,
752           S: Sample
753 {
754     type Item = Result<S>;
755 
next(&mut self) -> Option<Result<S>>756     fn next(&mut self) -> Option<Result<S>> {
757         iter_next(&mut self.reader)
758     }
759 
size_hint(&self) -> (usize, Option<usize>)760     fn size_hint(&self) -> (usize, Option<usize>) {
761         iter_size_hint(&self.reader)
762     }
763 }
764 
765 impl<'wr, R, S> ExactSizeIterator for WavSamples<'wr, R, S>
766     where R: io::Read,
767           S: Sample
768 {
769 }
770 
771 impl<R, S> Iterator for WavIntoSamples<R, S>
772     where R: io::Read,
773           S: Sample
774 {
775     type Item = Result<S>;
776 
next(&mut self) -> Option<Result<S>>777     fn next(&mut self) -> Option<Result<S>> {
778         iter_next(&mut self.reader)
779     }
780 
size_hint(&self) -> (usize, Option<usize>)781     fn size_hint(&self) -> (usize, Option<usize>) {
782         iter_size_hint(&self.reader)
783     }
784 }
785 
786 impl<R, S> ExactSizeIterator for WavIntoSamples<R, S>
787     where R: io::Read,
788           S: Sample
789 {
790 }
791 
792 #[test]
duration_and_len_agree()793 fn duration_and_len_agree() {
794     let files = &["testsamples/pcmwaveformat-16bit-44100Hz-mono.wav",
795                   "testsamples/waveformatex-16bit-44100Hz-stereo.wav",
796                   "testsamples/waveformatextensible-32bit-48kHz-stereo.wav"];
797 
798     for fname in files {
799         let reader = WavReader::open(fname).unwrap();
800         assert_eq!(reader.spec().channels as u32 * reader.duration(),
801                    reader.len());
802     }
803 }
804 
805 /// Tests reading a wave file with the PCMWAVEFORMAT struct.
806 #[test]
read_wav_pcm_wave_format_pcm()807 fn read_wav_pcm_wave_format_pcm() {
808     let mut wav_reader = WavReader::open("testsamples/pcmwaveformat-16bit-44100Hz-mono.wav")
809         .unwrap();
810 
811     assert_eq!(wav_reader.spec().channels, 1);
812     assert_eq!(wav_reader.spec().sample_rate, 44100);
813     assert_eq!(wav_reader.spec().bits_per_sample, 16);
814     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
815 
816     let samples: Vec<i16> = wav_reader.samples()
817         .map(|r| r.unwrap())
818         .collect();
819 
820     // The test file has been prepared with these exact four samples.
821     assert_eq!(&samples[..], &[2, -3, 5, -7]);
822 }
823 
824 #[test]
read_wav_skips_unknown_chunks()825 fn read_wav_skips_unknown_chunks() {
826     // The test samples are the same as without the -extra suffix, but ffmpeg
827     // has kindly added some useless chunks in between the fmt and data chunk.
828     let files = ["testsamples/pcmwaveformat-16bit-44100Hz-mono-extra.wav",
829                  "testsamples/waveformatex-16bit-44100Hz-mono-extra.wav"];
830 
831     for file in &files {
832         let mut wav_reader = WavReader::open(file).unwrap();
833 
834         assert_eq!(wav_reader.spec().channels, 1);
835         assert_eq!(wav_reader.spec().sample_rate, 44100);
836         assert_eq!(wav_reader.spec().bits_per_sample, 16);
837         assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
838 
839         let sample = wav_reader.samples::<i16>().next().unwrap().unwrap();
840         assert_eq!(sample, 2);
841     }
842 }
843 
844 #[test]
len_and_size_hint_are_correct()845 fn len_and_size_hint_are_correct() {
846     let mut wav_reader = WavReader::open("testsamples/pcmwaveformat-16bit-44100Hz-mono.wav")
847         .unwrap();
848 
849     assert_eq!(wav_reader.len(), 4);
850 
851     {
852         let mut samples = wav_reader.samples::<i16>();
853 
854         assert_eq!(samples.size_hint(), (4, Some(4)));
855         samples.next();
856         assert_eq!(samples.size_hint(), (3, Some(3)));
857     }
858 
859     // Reading should not affect the initial length.
860     assert_eq!(wav_reader.len(), 4);
861 
862     // Creating a new iterator resumes where the previous iterator stopped.
863     {
864         let mut samples = wav_reader.samples::<i16>();
865 
866         assert_eq!(samples.size_hint(), (3, Some(3)));
867         samples.next();
868         assert_eq!(samples.size_hint(), (2, Some(2)));
869     }
870 }
871 
872 #[test]
size_hint_is_exact()873 fn size_hint_is_exact() {
874     let files = &["testsamples/pcmwaveformat-16bit-44100Hz-mono.wav",
875                   "testsamples/waveformatex-16bit-44100Hz-stereo.wav",
876                   "testsamples/waveformatextensible-32bit-48kHz-stereo.wav"];
877 
878     for fname in files {
879         let mut reader = WavReader::open(fname).unwrap();
880         let len = reader.len();
881         let mut iter = reader.samples::<i32>();
882         for i in 0..len {
883             let remaining = (len - i) as usize;
884             assert_eq!(iter.size_hint(), (remaining, Some(remaining)));
885             assert!(iter.next().is_some());
886         }
887         assert!(iter.next().is_none());
888     }
889 }
890 
891 #[test]
samples_equals_into_samples()892 fn samples_equals_into_samples() {
893     let wav_reader_val = WavReader::open("testsamples/pcmwaveformat-8bit-44100Hz-mono.wav").unwrap();
894     let mut wav_reader_ref = WavReader::open("testsamples/pcmwaveformat-8bit-44100Hz-mono.wav").unwrap();
895 
896     let samples_val: Vec<i16> = wav_reader_val.into_samples()
897                                               .map(|r| r.unwrap())
898                                               .collect();
899 
900     let samples_ref: Vec<i16> = wav_reader_ref.samples()
901                                               .map(|r| r.unwrap())
902                                               .collect();
903 
904     assert_eq!(samples_val, samples_ref);
905 }
906 
907 /// Tests reading a wave file with the WAVEFORMATEX struct.
908 #[test]
read_wav_wave_format_ex_pcm()909 fn read_wav_wave_format_ex_pcm() {
910     let mut wav_reader = WavReader::open("testsamples/waveformatex-16bit-44100Hz-mono.wav")
911         .unwrap();
912 
913     assert_eq!(wav_reader.spec().channels, 1);
914     assert_eq!(wav_reader.spec().sample_rate, 44100);
915     assert_eq!(wav_reader.spec().bits_per_sample, 16);
916     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
917 
918     let samples: Vec<i16> = wav_reader.samples()
919                                       .map(|r| r.unwrap())
920                                       .collect();
921 
922     // The test file has been prepared with these exact four samples.
923     assert_eq!(&samples[..], &[2, -3, 5, -7]);
924 }
925 
926 #[test]
read_wav_wave_format_ex_ieee_float()927 fn read_wav_wave_format_ex_ieee_float() {
928     let mut wav_reader = WavReader::open("testsamples/waveformatex-ieeefloat-44100Hz-mono.wav")
929         .unwrap();
930 
931     assert_eq!(wav_reader.spec().channels, 1);
932     assert_eq!(wav_reader.spec().sample_rate, 44100);
933     assert_eq!(wav_reader.spec().bits_per_sample, 32);
934     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Float);
935 
936     let samples: Vec<f32> = wav_reader.samples()
937                                       .map(|r| r.unwrap())
938                                       .collect();
939 
940     // The test file has been prepared with these exact four samples.
941     assert_eq!(&samples[..], &[2.0, 3.0, -16411.0, 1019.0]);
942 }
943 
944 #[test]
read_wav_stereo()945 fn read_wav_stereo() {
946     let mut wav_reader = WavReader::open("testsamples/waveformatex-16bit-44100Hz-stereo.wav")
947         .unwrap();
948 
949     assert_eq!(wav_reader.spec().channels, 2);
950     assert_eq!(wav_reader.spec().sample_rate, 44100);
951     assert_eq!(wav_reader.spec().bits_per_sample, 16);
952     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
953 
954     let samples: Vec<i16> = wav_reader.samples()
955                                       .map(|r| r.unwrap())
956                                       .collect();
957 
958     // The test file has been prepared with these exact eight samples.
959     assert_eq!(&samples[..], &[2, -3, 5, -7, 11, -13, 17, -19]);
960 
961 }
962 
963 #[test]
read_wav_pcm_wave_format_8bit()964 fn read_wav_pcm_wave_format_8bit() {
965     let mut wav_reader = WavReader::open("testsamples/pcmwaveformat-8bit-44100Hz-mono.wav")
966                                    .unwrap();
967 
968     assert_eq!(wav_reader.spec().channels, 1);
969     assert_eq!(wav_reader.spec().bits_per_sample, 8);
970     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
971 
972     let samples: Vec<i16> = wav_reader.samples()
973                                       .map(|r| r.unwrap())
974                                       .collect();
975 
976     // The test file has been prepared with these exact four samples.
977     assert_eq!(&samples[..], &[19, -53, 89, -127]);
978 }
979 
980 /// Regression test for a real-world wav file encountered in Quake.
981 #[test]
read_wav_wave_format_ex_8bit()982 fn read_wav_wave_format_ex_8bit() {
983     let mut wav_reader = WavReader::open("testsamples/waveformatex-8bit-11025Hz-mono.wav").unwrap();
984 
985     assert_eq!(wav_reader.spec().channels, 1);
986     assert_eq!(wav_reader.spec().bits_per_sample, 8);
987     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
988 
989     let samples: Vec<i32> = wav_reader.samples()
990                                       .map(|r| r.unwrap())
991                                       .collect();
992 
993     // The audio data has been zeroed out, but for 8-bit files, a zero means a
994     // sample value of 128.
995     assert_eq!(&samples[..], &[-128, -128, -128, -128]);
996 }
997 
998 /// This test sample tests both reading the WAVEFORMATEXTENSIBLE header, and 24-bit samples.
999 #[test]
read_wav_wave_format_extensible_pcm_24bit()1000 fn read_wav_wave_format_extensible_pcm_24bit() {
1001     let mut wav_reader = WavReader::open("testsamples/waveformatextensible-24bit-192kHz-mono.wav")
1002         .unwrap();
1003 
1004     assert_eq!(wav_reader.spec().channels, 1);
1005     assert_eq!(wav_reader.spec().sample_rate, 192_000);
1006     assert_eq!(wav_reader.spec().bits_per_sample, 24);
1007     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
1008 
1009     let samples: Vec<i32> = wav_reader.samples()
1010                                       .map(|r| r.unwrap())
1011                                       .collect();
1012 
1013     // The test file has been prepared with these exact four samples.
1014     assert_eq!(&samples[..], &[-17, 4_194_319, -6_291_437, 8_355_817]);
1015 }
1016 
1017 #[test]
read_wav_32bit()1018 fn read_wav_32bit() {
1019     let mut wav_reader = WavReader::open("testsamples/waveformatextensible-32bit-48kHz-stereo.wav")
1020                                    .unwrap();
1021 
1022     assert_eq!(wav_reader.spec().bits_per_sample, 32);
1023     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
1024 
1025     let samples: Vec<i32> = wav_reader.samples()
1026                                       .map(|r| r.unwrap())
1027                                       .collect();
1028 
1029     // The test file has been prepared with these exact four samples.
1030     assert_eq!(&samples[..], &[19, -229_373, 33_587_161, -2_147_483_497]);
1031 }
1032 
1033 #[test]
read_wav_wave_format_extensible_ieee_float()1034 fn read_wav_wave_format_extensible_ieee_float() {
1035     let mut wav_reader =
1036         WavReader::open("testsamples/waveformatextensible-ieeefloat-44100Hz-mono.wav").unwrap();
1037 
1038     assert_eq!(wav_reader.spec().channels, 1);
1039     assert_eq!(wav_reader.spec().sample_rate, 44100);
1040     assert_eq!(wav_reader.spec().bits_per_sample, 32);
1041     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Float);
1042 
1043     let samples: Vec<f32> = wav_reader.samples()
1044                                       .map(|r| r.unwrap())
1045                                       .collect();
1046 
1047     // The test file has been prepared with these exact four samples.
1048     assert_eq!(&samples[..], &[2.0, 3.0, -16411.0, 1019.0]);
1049 }
1050 
1051 #[test]
read_wav_nonstandard_01()1052 fn read_wav_nonstandard_01() {
1053     // The test sample here is adapted from a file encountered in the wild (data
1054     // chunk replaced with two zero samples, some metadata dropped, and the file
1055     // length in the header fixed). It is not a valid file according to the
1056     // standard, but many players can deal with it nonetheless. (The file even
1057     // contains some metadata; open it in a hex editor if you would like to know
1058     // which program created it.) The file contains a regular PCM format tag,
1059     // but the size of the fmt chunk is one that would be expected of a
1060     // WAVEFORMATEXTENSIBLE chunk. The bits per sample is 24, which is invalid
1061     // for WAVEFORMATEX, but we can read it nonetheless.
1062     let mut wav_reader = WavReader::open("testsamples/nonstandard-01.wav").unwrap();
1063 
1064     assert_eq!(wav_reader.spec().bits_per_sample, 24);
1065     assert_eq!(wav_reader.spec().sample_format, SampleFormat::Int);
1066 
1067     let samples: Vec<i32> = wav_reader.samples()
1068                                       .map(|r| r.unwrap())
1069                                       .collect();
1070 
1071     assert_eq!(&samples[..], &[0, 0]);
1072 }
1073 
1074 #[test]
wide_read_should_signal_error()1075 fn wide_read_should_signal_error() {
1076     let mut reader24 = WavReader::open("testsamples/waveformatextensible-24bit-192kHz-mono.wav")
1077         .unwrap();
1078 
1079     // Even though we know the first value is 17, and it should fit in an `i8`,
1080     // a general 24-bit sample will not fit in an `i8`, so this should fail.
1081     // 16-bit is still not wide enough, but 32-bit should do the trick.
1082     assert!(reader24.samples::<i8>().next().unwrap().is_err());
1083     assert!(reader24.samples::<i16>().next().unwrap().is_err());
1084     assert!(reader24.samples::<i32>().next().unwrap().is_ok());
1085 
1086     let mut reader32 = WavReader::open("testsamples/waveformatextensible-32bit-48kHz-stereo.wav")
1087         .unwrap();
1088 
1089     // In general, 32-bit samples will not fit in anything but an `i32`.
1090     assert!(reader32.samples::<i8>().next().unwrap().is_err());
1091     assert!(reader32.samples::<i16>().next().unwrap().is_err());
1092     assert!(reader32.samples::<i32>().next().unwrap().is_ok());
1093 }
1094 
1095 #[test]
sample_format_mismatch_should_signal_error()1096 fn sample_format_mismatch_should_signal_error() {
1097     let mut reader_f32 = WavReader::open("testsamples/waveformatex-ieeefloat-44100Hz-mono.wav")
1098         .unwrap();
1099 
1100     assert!(reader_f32.samples::<i8>().next().unwrap().is_err());
1101     assert!(reader_f32.samples::<i16>().next().unwrap().is_err());
1102     assert!(reader_f32.samples::<i32>().next().unwrap().is_err());
1103     assert!(reader_f32.samples::<f32>().next().unwrap().is_ok());
1104 
1105     let mut reader_i8 = WavReader::open("testsamples/pcmwaveformat-8bit-44100Hz-mono.wav").unwrap();
1106 
1107     assert!(reader_i8.samples::<i8>().next().unwrap().is_ok());
1108     assert!(reader_i8.samples::<i16>().next().unwrap().is_ok());
1109     assert!(reader_i8.samples::<i32>().next().unwrap().is_ok());
1110     assert!(reader_i8.samples::<f32>().next().unwrap().is_err());
1111 }
1112 
1113 #[test]
fuzz_crashes_should_be_fixed()1114 fn fuzz_crashes_should_be_fixed() {
1115     use std::fs;
1116     use std::ffi::OsStr;
1117 
1118     // This is a regression test: all crashes and other issues found through
1119     // fuzzing should not cause a crash.
1120     let dir = fs::read_dir("testsamples/fuzz").ok()
1121                  .expect("failed to enumerate fuzz test corpus");
1122     for path in dir {
1123         let path = path.ok().expect("failed to obtain path info").path();
1124         let is_file = fs::metadata(&path).unwrap().file_type().is_file();
1125         if is_file && path.extension() == Some(OsStr::new("wav")) {
1126             println!("    testing {} ...", path.to_str()
1127                                                .expect("unsupported filename"));
1128             let mut reader = match WavReader::open(path) {
1129                 Ok(r) => r,
1130                 Err(..) => continue,
1131             };
1132             match reader.spec().sample_format {
1133                 SampleFormat::Int => {
1134                     for sample in reader.samples::<i32>() {
1135                         match sample {
1136                             Ok(..) => { }
1137                             Err(..) => break,
1138                         }
1139                     }
1140                 }
1141                 SampleFormat::Float => {
1142                     for sample in reader.samples::<f32>() {
1143                         match sample {
1144                             Ok(..) => { }
1145                             Err(..) => break,
1146                         }
1147                     }
1148                 }
1149             }
1150         }
1151     }
1152 }
1153 
1154 #[test]
seek_is_consistent()1155 fn seek_is_consistent() {
1156     let files = &["testsamples/pcmwaveformat-16bit-44100Hz-mono.wav",
1157                   "testsamples/waveformatex-16bit-44100Hz-stereo.wav",
1158                   "testsamples/waveformatextensible-32bit-48kHz-stereo.wav"];
1159     for fname in files {
1160         let mut reader = WavReader::open(fname).unwrap();
1161 
1162         // Seeking back to the start should "reset" the reader.
1163         let count = reader.samples::<i32>().count();
1164         reader.seek(0).unwrap();
1165         assert_eq!(reader.samples_read, 0);
1166         assert_eq!(count, reader.samples::<i32>().count());
1167 
1168         // Seek to the last sample.
1169         let last_time = reader.duration() - 1;
1170         let channels = reader.spec.channels;
1171         reader.seek(last_time).unwrap();
1172         {
1173             let mut samples = reader.samples::<i32>();
1174             for _ in 0..channels {
1175                 assert!(samples.next().is_some());
1176             }
1177             assert!(samples.next().is_none());
1178         }
1179 
1180         // Seeking beyond the audio data produces no samples.
1181         let num_samples = reader.len();
1182         reader.seek(num_samples).unwrap();
1183         assert!(reader.samples::<i32>().next().is_none());
1184         reader.seek(::std::u32::MAX / channels as u32).unwrap();
1185         assert!(reader.samples::<i32>().next().is_none());
1186     }
1187 }
1188