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}