Coverage Report

Created: 2025-09-04 06:37

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