surge_hound/
read.rs

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