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::fs;
14 use std::io;
15 use std::mem;
16 use std::io::{Seek, Write};
17 use std::mem::MaybeUninit;
18 use std::path;
19 use super::{Error, Result, Sample, SampleFormat, WavSpec, WavSpecEx};
20 use ::read;
21 
22 /// Extends the functionality of `io::Write` with additional methods.
23 ///
24 /// The methods may be used on any type that implements `io::Write`.
25 pub trait WriteExt: io::Write {
26     /// Writes an unsigned 8-bit integer.
write_u8(&mut self, x: u8) -> io::Result<()>27     fn write_u8(&mut self, x: u8) -> io::Result<()>;
28 
29     /// Writes a signed 16-bit integer in little endian format.
write_le_i16(&mut self, x: i16) -> io::Result<()>30     fn write_le_i16(&mut self, x: i16) -> io::Result<()>;
31 
32     /// Writes an unsigned 16-bit integer in little endian format.
write_le_u16(&mut self, x: u16) -> io::Result<()>33     fn write_le_u16(&mut self, x: u16) -> io::Result<()>;
34 
35     /// Writes a signed 24-bit integer in little endian format.
36     ///
37     /// The most significant byte of the `i32` is ignored.
write_le_i24(&mut self, x: i32) -> io::Result<()>38     fn write_le_i24(&mut self, x: i32) -> io::Result<()>;
39 
40     /// Writes a signed 24-bit integer in 4-byte little endian format.
41     ///
42     /// The most significant byte of the `i32` is replaced with zeroes.
write_le_i24_4(&mut self, x: i32) -> io::Result<()>43     fn write_le_i24_4(&mut self, x: i32) -> io::Result<()>;
44 
45     /// Writes an unsigned 24-bit integer in little endian format.
46     ///
47     /// The most significant byte of the `u32` is ignored.
write_le_u24(&mut self, x: u32) -> io::Result<()>48     fn write_le_u24(&mut self, x: u32) -> io::Result<()>;
49 
50     /// Writes a signed 32-bit integer in little endian format.
write_le_i32(&mut self, x: i32) -> io::Result<()>51     fn write_le_i32(&mut self, x: i32) -> io::Result<()>;
52 
53     /// Writes an unsigned 32-bit integer in little endian format.
write_le_u32(&mut self, x: u32) -> io::Result<()>54     fn write_le_u32(&mut self, x: u32) -> io::Result<()>;
55 
56     /// Writes an IEEE float in little endian format.
write_le_f32(&mut self, x: f32) -> io::Result<()>57     fn write_le_f32(&mut self, x: f32) -> io::Result<()>;
58 }
59 
60 impl<W> WriteExt for W
61     where W: io::Write
62 {
63     #[inline(always)]
write_u8(&mut self, x: u8) -> io::Result<()>64     fn write_u8(&mut self, x: u8) -> io::Result<()> {
65         let buf = [x];
66         self.write_all(&buf)
67     }
68 
69     #[inline(always)]
write_le_i16(&mut self, x: i16) -> io::Result<()>70     fn write_le_i16(&mut self, x: i16) -> io::Result<()> {
71         self.write_le_u16(x as u16)
72     }
73 
74     #[inline(always)]
write_le_u16(&mut self, x: u16) -> io::Result<()>75     fn write_le_u16(&mut self, x: u16) -> io::Result<()> {
76         let mut buf = [0u8; 2];
77         buf[0] = (x & 0xff) as u8;
78         buf[1] = (x >> 8) as u8;
79         self.write_all(&buf)
80     }
81 
82     #[inline(always)]
write_le_i24(&mut self, x: i32) -> io::Result<()>83     fn write_le_i24(&mut self, x: i32) -> io::Result<()> {
84         self.write_le_u24(x as u32)
85     }
86 
87     #[inline(always)]
write_le_i24_4(&mut self, x: i32) -> io::Result<()>88     fn write_le_i24_4(&mut self, x: i32) -> io::Result<()> {
89         self.write_le_u32((x as u32) & 0x00_ff_ff_ff)
90     }
91 
92     #[inline(always)]
write_le_u24(&mut self, x: u32) -> io::Result<()>93     fn write_le_u24(&mut self, x: u32) -> io::Result<()> {
94         let mut buf = [0u8; 3];
95         buf[0] = ((x >> 00) & 0xff) as u8;
96         buf[1] = ((x >> 08) & 0xff) as u8;
97         buf[2] = ((x >> 16) & 0xff) as u8;
98         self.write_all(&buf)
99     }
100 
101     #[inline(always)]
write_le_i32(&mut self, x: i32) -> io::Result<()>102     fn write_le_i32(&mut self, x: i32) -> io::Result<()> {
103         self.write_le_u32(x as u32)
104     }
105 
106     #[inline(always)]
write_le_u32(&mut self, x: u32) -> io::Result<()>107     fn write_le_u32(&mut self, x: u32) -> io::Result<()> {
108         let mut buf = [0u8; 4];
109         buf[0] = ((x >> 00) & 0xff) as u8;
110         buf[1] = ((x >> 08) & 0xff) as u8;
111         buf[2] = ((x >> 16) & 0xff) as u8;
112         buf[3] = ((x >> 24) & 0xff) as u8;
113         self.write_all(&buf)
114     }
115 
116     #[inline(always)]
write_le_f32(&mut self, x: f32) -> io::Result<()>117     fn write_le_f32(&mut self, x: f32) -> io::Result<()> {
118         let u = unsafe { mem::transmute::<f32, u32>(x) };
119         self.write_le_u32(u)
120     }
121 }
122 
123 /// Generates a bitmask with `channels` ones in the least significant bits.
124 ///
125 /// According to the [spec](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ksmedia/ns-ksmedia-waveformatextensible#remarks),
126 /// if `channels` is greater than the number of bits in the channel mask, 18 non-reserved bits,
127 /// extra channels are not assigned to any physical speaker location.  In this scenario, this
128 /// function will return a filled channel mask.
channel_mask(channels: u16) -> u32129 fn channel_mask(channels: u16) -> u32 {
130     // Clamp to 0-18 to stay within reserved bits.
131     let channels = if channels > 18 { 18 } else { channels };
132     (0..channels as u32).map(|c| 1 << c).fold(0, |a, c| a | c)
133 }
134 
135 #[test]
verify_channel_mask()136 fn verify_channel_mask() {
137     assert_eq!(channel_mask(0), 0);
138     assert_eq!(channel_mask(1), 1);
139     assert_eq!(channel_mask(2), 3);
140     assert_eq!(channel_mask(3), 7);
141     assert_eq!(channel_mask(4), 0xF);
142     assert_eq!(channel_mask(8), 0xFF);
143     assert_eq!(channel_mask(16), 0xFFFF);
144     // expect channels >= 18 to yield the same mask
145     assert_eq!(channel_mask(18), 0x3FFFF);
146     assert_eq!(channel_mask(32), 0x3FFFF);
147     assert_eq!(channel_mask(64), 0x3FFFF);
148     assert_eq!(channel_mask(129), 0x3FFFF);
149 }
150 
151 /// A writer that accepts samples and writes the WAVE format.
152 ///
153 /// The writer needs a `WavSpec` or `WavSpecEx` that describes the audio
154 /// properties. Then samples can be written with `write_sample`. Channel data is
155 /// interleaved. The number of samples written must be a multiple of the number
156 /// of channels. After all samples have been written, the file must be
157 /// finalized. This can be done by calling `finalize`. If `finalize` is not
158 /// called, the file will be finalized upon drop. However, finalization may
159 /// fail, and without calling `finalize`, such a failure cannot be observed.
160 pub struct WavWriter<W>
161     where W: io::Write + io::Seek
162 {
163     /// Specifies properties of the audio data.
164     spec: WavSpec,
165 
166     /// The (container) bytes per sample. This is the bit rate / 8 rounded up.
167     bytes_per_sample: u16,
168 
169     /// The writer that will be written to.
170     writer: W,
171 
172     /// The number of bytes written to the data section.
173     ///
174     /// This is an `u32` because WAVE cannot accomodate more data.
175     data_bytes_written: u32,
176 
177     /// Whether the header has been finalized.
178     finalized: bool,
179 
180     /// The buffer for the sample writer, which is recycled throughout calls to
181     /// avoid allocating frequently.
182     sample_writer_buffer: Vec<MaybeUninit<u8>>,
183 
184     /// The offset of the length field of the data chunk.
185     ///
186     /// This field needs to be overwritten after all data has been written. To
187     /// support different size fmt chunks, and other chunks interspersed, the
188     /// offset is flexible.
189     data_len_offset: u32,
190 }
191 
192 enum FmtKind {
193     PcmWaveFormat,
194     WaveFormatExtensible,
195 }
196 
197 impl<W> WavWriter<W>
198     where W: io::Write + io::Seek
199 {
200     /// Creates a writer that writes the WAVE format to the underlying writer.
201     ///
202     /// The underlying writer is assumed to be at offset 0. `WavWriter` employs
203     /// *no* buffering internally. It is recommended to wrap the writer in a
204     /// `BufWriter` to avoid too many `write` calls. The `create()` constructor
205     /// does this automatically.
206     ///
207     /// This writes parts of the header immediately, hence a `Result` is
208     /// returned.
new(writer: W, spec: WavSpec) -> Result<WavWriter<W>>209     pub fn new(writer: W, spec: WavSpec) -> Result<WavWriter<W>> {
210         let spec_ex = WavSpecEx {
211             spec: spec,
212             bytes_per_sample: (spec.bits_per_sample + 7) / 8,
213         };
214         WavWriter::new_with_spec_ex(writer, spec_ex)
215     }
216 
217 
218     /// Creates a writer that writes the WAVE format to the underlying writer.
219     ///
220     /// The underlying writer is assumed to be at offset 0. `WavWriter` employs
221     /// *no* buffering internally. It is recommended to wrap the writer in a
222     /// `BufWriter` to avoid too many `write` calls. The `create()` constructor
223     /// does this automatically.
224     ///
225     /// This writes parts of the header immediately, hence a `Result` is
226     /// returned.
new_with_spec_ex(writer: W, spec_ex: WavSpecEx) -> Result<WavWriter<W>>227     pub fn new_with_spec_ex(writer: W, spec_ex: WavSpecEx) -> Result<WavWriter<W>> {
228         let spec = spec_ex.spec;
229 
230         // Write the older PCMWAVEFORMAT structure if possible, because it is
231         // more widely supported. For more than two channels or more than 16
232         // bits per sample, the newer WAVEFORMATEXTENSIBLE is required. See also
233         // https://msdn.microsoft.com/en-us/library/ms713497.aspx.
234         let fmt_kind = if spec.channels > 2 || spec.bits_per_sample > 16 {
235             FmtKind::WaveFormatExtensible
236         } else {
237             FmtKind::PcmWaveFormat
238         };
239 
240         let mut writer = WavWriter {
241             spec: spec,
242             bytes_per_sample: spec_ex.bytes_per_sample,
243             writer: writer,
244             data_bytes_written: 0,
245             sample_writer_buffer: Vec::new(),
246             finalized: false,
247             data_len_offset: match fmt_kind {
248                 FmtKind::WaveFormatExtensible => 64,
249                 FmtKind::PcmWaveFormat => 40,
250             },
251         };
252 
253         // Hound can only write those bit depths. If something else was
254         // requested, fail early, rather than writing a header but then failing
255         // at the first sample.
256         let supported = match spec.bits_per_sample {
257             8 => true,
258             16 => true,
259             24 => true,
260             32 => true,
261             _ => false,
262         };
263 
264         if !supported {
265             return Err(Error::Unsupported)
266         }
267 
268         // Write headers, up to the point where data should be written.
269         try!(writer.write_headers(fmt_kind));
270 
271         Ok(writer)
272     }
273 
274     /// Writes the RIFF WAVE header, fmt chunk, and data chunk header.
write_headers(&mut self, fmt_kind: FmtKind) -> io::Result<()>275     fn write_headers(&mut self, fmt_kind: FmtKind) -> io::Result<()> {
276         // Write to an in-memory buffer before writing to the underlying writer.
277         let mut header = [0u8; 68];
278 
279         {
280             let mut buffer = io::Cursor::new(&mut header[..]);
281 
282             // Write the headers for the RIFF WAVE format.
283             try!(buffer.write_all("RIFF".as_bytes()));
284 
285             // Skip 4 bytes that will be filled with the file size afterwards.
286             try!(buffer.write_le_u32(0));
287 
288             try!(buffer.write_all("WAVE".as_bytes()));
289             try!(buffer.write_all("fmt ".as_bytes()));
290 
291             match fmt_kind {
292                 FmtKind::PcmWaveFormat => {
293                     try!(self.write_pcmwaveformat(&mut buffer));
294                 }
295                 FmtKind::WaveFormatExtensible => {
296                     try!(self.write_waveformatextensible(&mut buffer));
297                 }
298             }
299 
300             // Finally the header of the "data" chunk. The number of bytes
301             // that this will take is not known at this point. The 0 will
302             // be overwritten later.
303             try!(buffer.write_all("data".as_bytes()));
304             try!(buffer.write_le_u32(0));
305         }
306 
307         // The data length field are the last 4 bytes of the header.
308         let header_len = self.data_len_offset as usize + 4;
309 
310         self.writer.write_all(&header[..header_len])
311     }
312 
313     /// Writes the spec as a WAVEFORMAT structure.
314     ///
315     /// The `WAVEFORMAT` struct is a subset of both `WAVEFORMATEX` and
316     /// `WAVEFORMATEXTENSIBLE`. This does not write the `wFormatTag` member.
write_waveformat(&self, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()>317     fn write_waveformat(&self, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()> {
318         let spec = &self.spec;
319         // The field nChannels.
320         try!(buffer.write_le_u16(spec.channels));
321 
322         // The field nSamplesPerSec.
323         try!(buffer.write_le_u32(spec.sample_rate));
324         let bytes_per_sec = spec.sample_rate
325                           * self.bytes_per_sample as u32
326                           * spec.channels as u32;
327 
328         // The field nAvgBytesPerSec;
329         try!(buffer.write_le_u32(bytes_per_sec));
330 
331         // The field nBlockAlign. Block align * sample rate = bytes per sec.
332         try!(buffer.write_le_u16((bytes_per_sec / spec.sample_rate) as u16));
333 
334         Ok(())
335     }
336 
337     /// Writes the content of the fmt chunk as PCMWAVEFORMAT struct.
write_pcmwaveformat(&mut self, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()>338     fn write_pcmwaveformat(&mut self, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()> {
339         // Write the size of the WAVE header chunk.
340         try!(buffer.write_le_u32(16));
341 
342         // The following is based on the PCMWAVEFORMAT struct as documented at
343         // https://msdn.microsoft.com/en-us/library/ms712832.aspx. See also
344         // http://soundfile.sapp.org/doc/WaveFormat/.
345 
346         // The field wFormatTag
347         match self.spec.sample_format {
348             // WAVE_FORMAT_PCM
349             SampleFormat::Int => {
350                 try!(buffer.write_le_u16(1));
351             },
352             // WAVE_FORMAT_IEEE_FLOAT
353             SampleFormat::Float => {
354                 if self.spec.bits_per_sample == 32 {
355                     try!(buffer.write_le_u16(3));
356                 } else {
357                     panic!("Invalid number of bits per sample. \
358                            When writing SampleFormat::Float, \
359                            bits_per_sample must be 32.");
360                 }
361             },
362         };
363 
364         try!(self.write_waveformat(buffer));
365 
366         // The field wBitsPerSample, the real number of bits per sample.
367         try!(buffer.write_le_u16(self.spec.bits_per_sample));
368 
369         // Note: for WAVEFORMATEX, there would be another 16-byte field `cbSize`
370         // here that should be set to zero. And the header size would be 18
371         // rather than 16.
372 
373         Ok(())
374     }
375 
376     /// Writes the contents of the fmt chunk as WAVEFORMATEXTENSIBLE struct.
write_waveformatextensible(&mut self, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()>377     fn write_waveformatextensible(&mut self, buffer: &mut io::Cursor<&mut [u8]>) -> io::Result<()> {
378         // Write the size of the WAVE header chunk.
379         try!(buffer.write_le_u32(40));
380 
381         // The following is based on the WAVEFORMATEXTENSIBLE struct, documented
382         // at https://msdn.microsoft.com/en-us/library/ms713496.aspx and
383         // https://msdn.microsoft.com/en-us/library/ms713462.aspx.
384 
385         // The field wFormatTag, value 1 means WAVE_FORMAT_PCM, but we use
386         // the slightly more sophisticated WAVE_FORMAT_EXTENSIBLE.
387         try!(buffer.write_le_u16(0xfffe));
388 
389         try!(self.write_waveformat(buffer));
390 
391         // The field wBitsPerSample. This is actually the size of the
392         // container, so this is a multiple of 8.
393         try!(buffer.write_le_u16(self.bytes_per_sample as u16 * 8));
394         // The field cbSize, the number of remaining bytes in the struct.
395         try!(buffer.write_le_u16(22));
396         // The field wValidBitsPerSample, the real number of bits per sample.
397         try!(buffer.write_le_u16(self.spec.bits_per_sample));
398         // The field dwChannelMask.
399         // TODO: add the option to specify the channel mask. For now, use
400         // the default assignment.
401         try!(buffer.write_le_u32(channel_mask(self.spec.channels)));
402 
403         // The field SubFormat.
404         let subformat_guid = match self.spec.sample_format {
405             // PCM audio with integer samples.
406             SampleFormat::Int => super::KSDATAFORMAT_SUBTYPE_PCM,
407             // PCM audio with 32-bit IEEE float samples.
408             SampleFormat::Float => {
409                 if self.spec.bits_per_sample == 32 {
410                     super::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
411                 } else {
412                     panic!("Invalid number of bits per sample. \
413                            When writing SampleFormat::Float, \
414                            bits_per_sample must be 32.");
415                 }
416             }
417         };
418         try!(buffer.write_all(&subformat_guid));
419 
420         Ok(())
421     }
422 
423     /// Writes a single sample for one channel.
424     ///
425     /// WAVE interleaves channel data, so the channel that this writes the
426     /// sample to depends on previous writes. This will return an error if the
427     /// sample does not fit in the number of bits specified in the `WavSpec`.
428     #[inline]
write_sample<S: Sample>(&mut self, sample: S) -> Result<()>429     pub fn write_sample<S: Sample>(&mut self, sample: S) -> Result<()> {
430         try!(sample.write_padded(
431             &mut self.writer,
432             self.spec.bits_per_sample,
433             self.bytes_per_sample,
434         ));
435         self.data_bytes_written += self.bytes_per_sample as u32;
436         Ok(())
437     }
438 
439     /// Create an efficient writer that writes 16-bit integer samples only.
440     ///
441     /// When it is known what the kind of samples will be, many dynamic checks
442     /// can be omitted. Furthermore, this writer employs buffering internally,
443     /// which allows omitting return value checks except on flush. The internal
444     /// buffer will be sized such that exactly `num_samples` samples can be
445     /// written to it, and the buffer is recycled across calls to
446     /// `get_i16_writer()` if the previous buffer was sufficiently large.
447     ///
448     /// # Panics
449     ///
450     /// Panics if the spec does not match a 16 bits per sample integer format.
451     ///
452     /// Attempting to write more than `num_samples` samples to the writer will
453     /// panic too.
get_i16_writer<'s>(&'s mut self, num_samples: u32) -> SampleWriter16<'s, W>454     pub fn get_i16_writer<'s>(&'s mut self,
455                               num_samples: u32)
456                               -> SampleWriter16<'s, W> {
457         if self.spec.sample_format != SampleFormat::Int {
458             panic!("When calling get_i16_writer, the sample format must be int.");
459         }
460         if self.spec.bits_per_sample != 16 {
461             panic!("When calling get_i16_writer, the number of bits per sample must be 16.");
462         }
463 
464         let num_bytes = num_samples as usize * 2;
465 
466         if self.sample_writer_buffer.len() < num_bytes {
467             // We need a bigger buffer. There is no point in growing the old
468             // one, as we are going to overwrite the samples anyway, so just
469             // allocate a new one.
470             let mut new_buffer = Vec::<MaybeUninit<u8>>::with_capacity(num_bytes);
471 
472             // The potentially garbage memory here will not be exposed: the
473             // buffer is only exposed when flushing, but `flush()` asserts that
474             // all samples have been written.
475             unsafe { new_buffer.set_len(num_bytes); }
476 
477             self.sample_writer_buffer = new_buffer;
478         }
479 
480         SampleWriter16 {
481             writer: &mut self.writer,
482             buffer: &mut self.sample_writer_buffer[..num_bytes],
483             data_bytes_written: &mut self.data_bytes_written,
484             index: 0,
485         }
486     }
487 
update_header(&mut self) -> Result<()>488     fn update_header(&mut self) -> Result<()> {
489         // The header size minus magic and 32-bit filesize (8 bytes).
490         // The data chunk length (4 bytes) is the last part of the header.
491         let header_size = self.data_len_offset + 4 - 8;
492         let file_size = self.data_bytes_written + header_size;
493 
494         try!(self.writer.seek(io::SeekFrom::Start(4)));
495         try!(self.writer.write_le_u32(file_size));
496         try!(self.writer.seek(io::SeekFrom::Start(self.data_len_offset as u64)));
497         try!(self.writer.write_le_u32(self.data_bytes_written));
498 
499         // Signal error if the last sample was not finished, but do so after
500         // everything has been written, so that no data is lost, even though
501         // the file is now ill-formed.
502         if (self.data_bytes_written / self.bytes_per_sample as u32)
503             % self.spec.channels as u32 != 0 {
504             Err(Error::UnfinishedSample)
505         } else {
506             Ok(())
507         }
508     }
509 
510     /// Updates the WAVE header and flushes the underlying writer.
511     ///
512     /// Flush writes the WAVE header to the underlying writer to make the
513     /// written bytes a valid wav file, and then flushes the writer. It is still
514     /// possible to write more samples after flushing.
515     ///
516     /// Flush can be used for “checkpointing”. Even if after the flush there is
517     /// an IO error or the writing process dies, the file can still be read by a
518     /// compliant decoder up to the last flush.
519     ///
520     /// Note that if the number of samples written is not a multiple of the
521     /// channel count, the intermediate wav file will not be valid. In that case
522     /// `flush()` will still flush the data and write the (invalid) wav file,
523     /// but `Error::UnfinishedSample` will be returned afterwards.
524     ///
525     /// It is not necessary to call `finalize()` directly after `flush()`, if no
526     /// samples have been written after flushing.
flush(&mut self) -> Result<()>527     pub fn flush(&mut self) -> Result<()> {
528         let current_pos = try!(self.writer.seek(io::SeekFrom::Current(0)));
529         try!(self.update_header());
530         try!(self.writer.flush());
531         try!(self.writer.seek(io::SeekFrom::Start(current_pos)));
532         Ok(())
533     }
534 
535     /// Updates the WAVE header (which requires knowing all samples).
536     ///
537     /// This method must be called after all samples have been written. If it
538     /// is not called, the destructor will finalize the file, but any errors
539     /// that occur in the process cannot be observed in that manner.
finalize(mut self) -> Result<()>540     pub fn finalize(mut self) -> Result<()> {
541         self.finalized = true;
542         try!(self.update_header());
543         // We need to perform a flush here to truly capture all errors before
544         // the writer is dropped: for a buffered writer, the write to the buffer
545         // may succeed, but the write to the underlying writer may fail. So
546         // flush explicitly.
547         try!(self.writer.flush());
548         Ok(())
549     }
550 
551     /// Returns information about the WAVE file being written.
552     ///
553     /// This is the same spec that was passed to `WavWriter::new()`. For a
554     /// writer constructed with `WavWriter::new_append()` or
555     /// `WavWriter::append()`, this method returns the spec of the file being
556     /// appended to.
spec(&self) -> WavSpec557     pub fn spec(&self) -> WavSpec {
558         self.spec
559     }
560 
561     /// Returns the duration of the file written so far, in samples.
562     ///
563     /// The duration is independent of the number of channels. It is expressed
564     /// in units of samples. The duration in seconds can be obtained by
565     /// dividing this number by the sample rate.
duration(&self) -> u32566     pub fn duration(&self) -> u32 {
567         self.data_bytes_written / (self.bytes_per_sample as u32 * self.spec.channels as u32)
568     }
569 
570     /// Returns the number of samples in the file written so far.
571     ///
572     /// The length of the file is its duration (in samples) times the number of
573     /// channels.
len(&self) -> u32574     pub fn len(&self) -> u32 {
575         self.data_bytes_written / self.bytes_per_sample as u32
576     }
577 }
578 
579 impl<W> Drop for WavWriter<W>
580     where W: io::Write + io::Seek
581 {
drop(&mut self)582     fn drop(&mut self) {
583         // If the file was not explicitly finalized (to update the headers), do
584         // it in the drop. This can fail, but drop should not panic, so a
585         // failure is ignored silently here.
586         if !self.finalized {
587             let _r = self.update_header();
588         }
589     }
590 }
591 
592 /// Reads the relevant parts of the header required to support append.
593 ///
594 /// Returns (spec_ex, data_len, data_len_offset).
read_append<W: io::Read + io::Seek>(mut reader: &mut W) -> Result<(WavSpecEx, u32, u32)>595 fn read_append<W: io::Read + io::Seek>(mut reader: &mut W) -> Result<(WavSpecEx, u32, u32)> {
596     let (spec_ex, data_len) = {
597         try!(read::read_wave_header(&mut reader));
598         try!(read::read_until_data(&mut reader))
599     };
600 
601     // Record the position of the data chunk length, so we can overwrite it
602     // later.
603     let data_len_offset = try!(reader.seek(io::SeekFrom::Current(0))) as u32 - 4;
604 
605     let spec = spec_ex.spec;
606     let num_samples = data_len / spec_ex.bytes_per_sample as u32;
607 
608     // There must not be trailing bytes in the data chunk, otherwise the
609     // bytes we write will be off.
610     if num_samples * spec_ex.bytes_per_sample as u32 != data_len {
611         let msg = "data chunk length is not a multiple of sample size";
612         return Err(Error::FormatError(msg));
613     }
614 
615     // Hound cannot read or write other bit depths than those, so rather
616     // than refusing to write later, fail early.
617     let supported = match (spec_ex.bytes_per_sample, spec.bits_per_sample) {
618         (1, 8) => true,
619         (2, 16) => true,
620         (3, 24) => true,
621         (4, 32) => true,
622         _ => false,
623     };
624 
625     if !supported {
626         return Err(Error::Unsupported);
627     }
628 
629     // The number of samples must be a multiple of the number of channels,
630     // otherwise the last inter-channel sample would not have data for all
631     // channels.
632     if num_samples % spec_ex.spec.channels as u32 != 0 {
633         return Err(Error::FormatError("invalid data chunk length"));
634     }
635 
636     Ok((spec_ex, data_len, data_len_offset))
637 }
638 
639 impl WavWriter<io::BufWriter<fs::File>> {
640     /// Creates a writer that writes the WAVE format to a file.
641     ///
642     /// This is a convenience constructor that creates the file, wraps it in a
643     /// `BufWriter`, and then constructs a `WavWriter` from it. The file will
644     /// be overwritten if it exists.
create<P: AsRef<path::Path>>(filename: P, spec: WavSpec) -> Result<WavWriter<io::BufWriter<fs::File>>>645     pub fn create<P: AsRef<path::Path>>(filename: P,
646                                         spec: WavSpec)
647                                         -> Result<WavWriter<io::BufWriter<fs::File>>> {
648         let file = try!(fs::File::create(filename));
649         let buf_writer = io::BufWriter::new(file);
650         WavWriter::new(buf_writer, spec)
651     }
652 
653     /// Creates a writer that appends samples to an existing file.
654     ///
655     /// This is a convenience constructor that opens the file in append mode,
656     /// reads its header using a buffered reader, and then constructs an
657     /// appending `WavWriter` that writes to the file using a `BufWriter`.
658     ///
659     /// See `WavWriter::new_append()` for more details about append behavior.
append<P: AsRef<path::Path>>(filename: P) -> Result<WavWriter<io::BufWriter<fs::File>>>660     pub fn append<P: AsRef<path::Path>>(filename: P) -> Result<WavWriter<io::BufWriter<fs::File>>> {
661         // Open the file in append mode, start reading from the start.
662         let mut file = try!(fs::OpenOptions::new().read(true).write(true).open(filename));
663         try!(file.seek(io::SeekFrom::Start(0)));
664 
665         // Read the header using a buffered reader.
666         let mut buf_reader = io::BufReader::new(file);
667         let (spec_ex, data_len, data_len_offset) = try!(read_append(&mut buf_reader));
668         let mut file = buf_reader.into_inner();
669 
670         // Seek to the data position, and from now on, write using a buffered
671         // writer.
672         try!(file.seek(io::SeekFrom::Current(data_len as i64)));
673         let buf_writer = io::BufWriter::new(file);
674 
675         let writer = WavWriter {
676             spec: spec_ex.spec,
677             bytes_per_sample: spec_ex.bytes_per_sample,
678             writer: buf_writer,
679             data_bytes_written: data_len,
680             sample_writer_buffer: Vec::new(),
681             finalized: false,
682             data_len_offset: data_len_offset,
683         };
684 
685         Ok(writer)
686     }
687 }
688 
689 impl<W> WavWriter<W> where W: io::Read + io::Write + io::Seek {
690     /// Creates a writer that appends samples to an existing file stream.
691     ///
692     /// This first reads the existing header to obtain the spec, then seeks to
693     /// the end of the writer. The writer then appends new samples to the end of
694     /// the stream.
695     ///
696     /// The underlying writer is assumed to be at offset 0.
697     ///
698     /// If the existing file includes a fact chunk, it will not be updated after
699     /// appending, and hence become outdated. For files produced by Hound this
700     /// is not an issue, because Hound never writes a fact chunk. For all the
701     /// formats that Hound can write, the fact chunk is redundant.
new_append(mut writer: W) -> Result<WavWriter<W>>702     pub fn new_append(mut writer: W) -> Result<WavWriter<W>> {
703         let (spec_ex, data_len, data_len_offset) = try!(read_append(&mut writer));
704         try!(writer.seek(io::SeekFrom::Current(data_len as i64)));
705         let writer = WavWriter {
706             spec: spec_ex.spec,
707             bytes_per_sample: spec_ex.bytes_per_sample,
708             writer: writer,
709             data_bytes_written: data_len,
710             sample_writer_buffer: Vec::new(),
711             finalized: false,
712             data_len_offset: data_len_offset,
713         };
714 
715         Ok(writer)
716     }
717 }
718 
719 
720 /// A writer that specifically only writes integer samples of 16 bits per sample.
721 ///
722 /// The writer buffers written samples internally so they can be written in a
723 /// single batch later on. This has two advantages when performance is
724 /// important:
725 ///
726 ///  * There is no need for error handling during writing, only on flush. This
727 ///    eliminates a lot of branches.
728 ///  * The buffer can be written once, which reduces the overhead of the write
729 ///    call. Because writing to an `io::BufWriter` is implemented with a
730 ///    `memcpy` (even for single bytes), there is a large overhead to writing
731 ///    small amounts of data such as a 16-bit sample. By writing large blocks
732 ///    (or by not using `BufWriter`) this overhead can be avoided.
733 ///
734 /// A `SampleWriter16` can be obtained by calling [`WavWriter::get_i16_writer`](
735 /// struct.WavWriter.html#method.get_i16_writer).
736 pub struct SampleWriter16<'parent, W> where W: io::Write + io::Seek + 'parent {
737     /// The writer borrowed from the wrapped WavWriter.
738     writer: &'parent mut W,
739 
740     /// The internal buffer that samples are written to before they are flushed.
741     buffer: &'parent mut [MaybeUninit<u8>],
742 
743     /// Reference to the `data_bytes_written` field of the writer.
744     data_bytes_written: &'parent mut u32,
745 
746     /// The index into the buffer where the next bytes will be written.
747     index: u32,
748 }
749 
750 impl<'parent, W: io::Write + io::Seek> SampleWriter16<'parent, W> {
751     /// Writes a single sample for one channel.
752     ///
753     /// WAVE interleaves channel data, so the channel that this writes the
754     /// sample to depends on previous writes.
755     ///
756     /// Unlike `WavWriter::write_sample()`, no range check is performed. Only
757     /// the least significant 16 bits are considered, everything else is
758     /// discarded.  Apart from that check, this method is more efficient than
759     /// `WavWriter::write_sample()`, because it can avoid dispatching on the
760     /// number of bits. That was done already when the `SampleWriter16` was
761     /// constructed.
762     ///
763     /// Note that nothing is actually written until `flush()` is called.
764     #[inline(always)]
write_sample<S: Sample>(&mut self, sample: S)765     pub fn write_sample<S: Sample>(&mut self, sample: S) {
766         assert!((self.index as usize) + 2 <= self.buffer.len(),
767           "Trying to write more samples than reserved for the sample writer.");
768 
769         // SAFETY: We performed the bounds check in the above assertion.
770         unsafe { self.write_sample_unchecked(sample) };
771     }
772 
write_u16_le_unchecked(&mut self, value: u16)773     unsafe fn write_u16_le_unchecked(&mut self, value: u16) {
774         // On little endian machines the compiler produces assembly code
775         // that merges the following two lines into a single instruction.
776         *self.buffer.get_unchecked_mut(self.index as usize) = MaybeUninit::new(value as u8);
777         self.buffer.get_unchecked_mut(self.index as usize).assume_init();
778         *self.buffer.get_unchecked_mut(self.index as usize + 1) = MaybeUninit::new((value >> 8) as u8);
779         self.buffer.get_unchecked_mut(self.index as usize + 1).assume_init();
780     }
781 
782     /// Like `write_sample()`, but does not perform a bounds check when writing
783     /// to the internal buffer.
784     ///
785     /// It is the responsibility of the programmer to ensure that no more
786     /// samples are written than allocated when the writer was created.
787     #[inline(always)]
write_sample_unchecked<S: Sample>(&mut self, sample: S)788     pub unsafe fn write_sample_unchecked<S: Sample>(&mut self, sample: S) {
789         self.write_u16_le_unchecked(sample.as_i16() as u16);
790         self.index += 2;
791     }
792 
793     /// Flush the internal buffer to the underlying writer.
794     ///
795     /// # Panics
796     ///
797     /// Panics if insufficient samples (less than specified when the writer was
798     /// constructed) have been written with `write_sample()`.
flush(self) -> Result<()>799     pub fn flush(self) -> Result<()> {
800         if self.index as usize != self.buffer.len() {
801             panic!("Insufficient samples written to the sample writer.");
802         }
803 
804         // SAFETY: casting `self.buffer` to a `*const [MaybeUninit<u8>]` is safe
805         // since the caller guarantees that `self.buffer` is initialized, and
806         // `MaybeUninit<u8>` is guaranteed to have the same layout as `u8`. The
807         // pointer obtained is valid since it refers to memory owned by
808         // `self.buffer` which is a reference and thus guaranteed to be valid
809         // for reads. This is copied from the nightly implementation for
810         // slice_assume_init_ref.
811         let slice = unsafe { &*(self.buffer as *const [MaybeUninit<u8>] as *const [u8]) };
812 
813         try!(self.writer.write_all(slice));
814 
815         *self.data_bytes_written += self.buffer.len() as u32;
816         Ok(())
817     }
818 }
819 
820 #[test]
short_write_should_signal_error()821 fn short_write_should_signal_error() {
822     use SampleFormat;
823 
824     let mut buffer = io::Cursor::new(Vec::new());
825 
826     let write_spec = WavSpec {
827         channels: 17,
828         sample_rate: 48000,
829         bits_per_sample: 8,
830         sample_format: SampleFormat::Int,
831     };
832 
833     // Deliberately write one sample less than 17 * 5.
834     let mut writer = WavWriter::new(&mut buffer, write_spec).unwrap();
835     for s in 0..17 * 5 - 1 {
836         writer.write_sample(s as i16).unwrap();
837     }
838     let error = writer.finalize().err().unwrap();
839 
840     match error {
841         Error::UnfinishedSample => {}
842         _ => panic!("UnfinishedSample error should have been returned."),
843     }
844 }
845 
846 #[test]
wide_write_should_signal_error()847 fn wide_write_should_signal_error() {
848     let mut buffer = io::Cursor::new(Vec::new());
849 
850     let spec8 = WavSpec {
851         channels: 1,
852         sample_rate: 44100,
853         bits_per_sample: 8,
854         sample_format: SampleFormat::Int,
855     };
856     {
857         let mut writer = WavWriter::new(&mut buffer, spec8).unwrap();
858         assert!(writer.write_sample(127_i8).is_ok());
859         assert!(writer.write_sample(127_i16).is_ok());
860         assert!(writer.write_sample(127_i32).is_ok());
861         assert!(writer.write_sample(128_i16).is_err());
862         assert!(writer.write_sample(128_i32).is_err());
863     }
864 
865     let spec16 = WavSpec { bits_per_sample: 16, ..spec8 };
866     {
867         let mut writer = WavWriter::new(&mut buffer, spec16).unwrap();
868         assert!(writer.write_sample(32767_i16).is_ok());
869         assert!(writer.write_sample(32767_i32).is_ok());
870         assert!(writer.write_sample(32768_i32).is_err());
871     }
872 
873     let spec24 = WavSpec { bits_per_sample: 24, ..spec8 };
874     {
875         let mut writer = WavWriter::new(&mut buffer, spec24).unwrap();
876         assert!(writer.write_sample(8_388_607_i32).is_ok());
877         assert!(writer.write_sample(8_388_608_i32).is_err());
878     }
879 }
880 
881 #[test]
s24_wav_write()882 fn s24_wav_write() {
883     use std::fs::File;
884     use std::io::Read;
885     let mut buffer = io::Cursor::new(Vec::new());
886 
887     let spec = WavSpecEx {
888         spec: WavSpec {
889             channels: 2,
890             sample_rate: 48000,
891             bits_per_sample: 24,
892             sample_format: SampleFormat::Int,
893         },
894         bytes_per_sample: 4,
895     };
896     {
897         let mut writer = WavWriter::new_with_spec_ex(&mut buffer, spec).unwrap();
898         assert!(writer.write_sample(-96_i32).is_ok());
899         assert!(writer.write_sample(23_052_i32).is_ok());
900         assert!(writer.write_sample(8_388_607_i32).is_ok());
901         assert!(writer.write_sample(-8_360_672_i32).is_ok());
902     }
903 
904     let mut expected = Vec::new();
905     File::open("testsamples/waveformatextensible-24bit-4byte-48kHz-stereo.wav")
906         .unwrap()
907         .read_to_end(&mut expected)
908         .unwrap();
909 
910     assert_eq!(buffer.into_inner(), expected);
911 }
912