hound/
write.rs

1// Hound -- A wav encoding and decoding library in Rust
2// Copyright (C) 2015 Ruud van Asseldonk
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// A copy of the License has been included in the root of the repository.
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use std::fs;
14use std::io;
15use std::mem;
16use std::io::{Seek, Write};
17use std::mem::MaybeUninit;
18use std::path;
19use super::{Error, Result, Sample, SampleFormat, WavSpec, WavSpecEx};
20use ::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`.
25pub trait WriteExt: io::Write {
26    /// Writes an unsigned 8-bit integer.
27    fn write_u8(&mut self, x: u8) -> io::Result<()>;
28
29    /// Writes a signed 16-bit integer in little endian format.
30    fn write_le_i16(&mut self, x: i16) -> io::Result<()>;
31
32    /// Writes an unsigned 16-bit integer in little endian format.
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.
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.
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.
48    fn write_le_u24(&mut self, x: u32) -> io::Result<()>;
49
50    /// Writes a signed 32-bit integer in little endian format.
51    fn write_le_i32(&mut self, x: i32) -> io::Result<()>;
52
53    /// Writes an unsigned 32-bit integer in little endian format.
54    fn write_le_u32(&mut self, x: u32) -> io::Result<()>;
55
56    /// Writes an IEEE float in little endian format.
57    fn write_le_f32(&mut self, x: f32) -> io::Result<()>;
58}
59
60impl<W> WriteExt for W
61    where W: io::Write
62{
63    #[inline(always)]
64    fn write_u8(&mut self, x: u8) -> io::Result<()> {
65        let buf = [x];
66        self.write_all(&buf)
67    }
68
69    #[inline(always)]
70    fn write_le_i16(&mut self, x: i16) -> io::Result<()> {
71        self.write_le_u16(x as u16)
72    }
73
74    #[inline(always)]
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)]
83    fn write_le_i24(&mut self, x: i32) -> io::Result<()> {
84        self.write_le_u24(x as u32)
85    }
86
87    #[inline(always)]
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)]
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)]
102    fn write_le_i32(&mut self, x: i32) -> io::Result<()> {
103        self.write_le_u32(x as u32)
104    }
105
106    #[inline(always)]
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)]
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.
129fn 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]
136fn 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.
160pub 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
192enum FmtKind {
193    PcmWaveFormat,
194    WaveFormatExtensible,
195}
196
197impl<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.
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.
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.
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.
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.
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.
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]
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.
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
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.
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.
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.
557    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.
566    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.
574    pub fn len(&self) -> u32 {
575        self.data_bytes_written / self.bytes_per_sample as u32
576    }
577}
578
579impl<W> Drop for WavWriter<W>
580    where W: io::Write + io::Seek
581{
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).
595fn 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
639impl 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.
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.
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
689impl<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.
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).
736pub 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
750impl<'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)]
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
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)]
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()`.
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]
821fn 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]
847fn 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]
882fn 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}