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