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