Coverage Report

Created: 2024-04-26 06:25

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