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