1#![warn(missing_docs)]
57
58use std::error;
59use std::fmt;
60use std::io;
61use std::result;
62use read::ReadExt;
63use write::WriteExt;
64
65mod read;
66mod write;
67
68pub use read::{WavReader, WavIntoSamples, WavSamples, read_wave_header, WavSpecSurge};
69pub use write::{SampleWriter16, WavWriter};
70
71pub trait Sample: Sized {
80 fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()>;
82
83 fn read<R: io::Read>(reader: &mut R, _: SampleFormat, bytes: u16, bits: u16) -> Result<Self>;
85
86 fn as_i16(&self) -> i16;
92}
93
94fn signed_from_u8(x: u8) -> i8 {
102 (x as i16 - 128) as i8
103}
104
105fn u8_from_signed(x: i8) -> u8 {
107 (x as i16 + 128) as u8
108}
109
110#[test]
111fn u8_sign_conversion_is_bijective() {
112 for x in 0..255 {
113 assert_eq!(x, u8_from_signed(signed_from_u8(x)));
114 }
115 for x in -128..127 {
116 assert_eq!(x, signed_from_u8(u8_from_signed(x)));
117 }
118}
119
120#[inline(always)]
122fn narrow_to_i8(x: i32) -> Result<i8> {
123 use std::i8;
124 if x < i8::MIN as i32 || x > i8::MAX as i32 {
125 Err(Error::TooWide)
126 } else {
127 Ok(x as i8)
128 }
129}
130
131#[test]
132fn verify_narrow_to_i8() {
133 assert!(narrow_to_i8(127).is_ok());
134 assert!(narrow_to_i8(128).is_err());
135 assert!(narrow_to_i8(-128).is_ok());
136 assert!(narrow_to_i8(-129).is_err());
137}
138
139#[inline(always)]
141fn narrow_to_i16(x: i32) -> Result<i16> {
142 use std::i16;
143 if x < i16::MIN as i32 || x > i16::MAX as i32 {
144 Err(Error::TooWide)
145 } else {
146 Ok(x as i16)
147 }
148}
149
150#[test]
151fn verify_narrow_to_i16() {
152 assert!(narrow_to_i16(32767).is_ok());
153 assert!(narrow_to_i16(32768).is_err());
154 assert!(narrow_to_i16(-32768).is_ok());
155 assert!(narrow_to_i16(-32769).is_err());
156}
157
158#[inline(always)]
160fn narrow_to_i24(x: i32) -> Result<i32> {
161 if x < -(1 << 23) || x > (1 << 23) - 1 {
162 Err(Error::TooWide)
163 } else {
164 Ok(x)
165 }
166}
167
168#[test]
169fn verify_narrow_to_i24() {
170 assert!(narrow_to_i24(8_388_607).is_ok());
171 assert!(narrow_to_i24(8_388_608).is_err());
172 assert!(narrow_to_i24(-8_388_608).is_ok());
173 assert!(narrow_to_i24(-8_388_609).is_err());
174}
175
176impl Sample for i8 {
177 fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()> {
178 match bits {
179 8 => Ok(writer.write_u8(u8_from_signed(self))?),
180 16 => Ok(writer.write_le_i16(self as i16)?),
181 24 => Ok(writer.write_le_i24(self as i32)?),
182 32 => Ok(writer.write_le_i32(self as i32)?),
183 _ => Err(Error::Unsupported),
184 }
185 }
186
187 #[inline(always)]
188 fn as_i16(&self) -> i16 {
189 *self as i16
190 }
191
192 fn read<R: io::Read>(reader: &mut R, fmt: SampleFormat, bytes: u16, bits: u16) -> Result<i8> {
193 if fmt != SampleFormat::Int {
194 return Err(Error::InvalidSampleFormat);
195 }
196 match (bytes, bits) {
197 (1, 8) => Ok(reader.read_u8().map(signed_from_u8)?),
198 (n, _) if n > 1 => Err(Error::TooWide),
199 _ => Err(Error::Unsupported),
201 }
202 }
203}
204
205impl Sample for i16 {
206 fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()> {
207 match bits {
208 8 => Ok(writer.write_u8(u8_from_signed(narrow_to_i8(self as i32)?))?),
209 16 => Ok(writer.write_le_i16(self)?),
210 24 => Ok(writer.write_le_i24(self as i32)?),
211 32 => Ok(writer.write_le_i32(self as i32)?),
212 _ => Err(Error::Unsupported),
213 }
214 }
215
216 #[inline(always)]
217 fn as_i16(&self) -> i16 {
218 *self
219 }
220
221 fn read<R: io::Read>(reader: &mut R, fmt: SampleFormat, bytes: u16, bits: u16) -> Result<i16> {
222 if fmt != SampleFormat::Int {
223 return Err(Error::InvalidSampleFormat);
224 }
225 match (bytes, bits) {
226 (1, 8) => Ok(reader.read_u8().map(signed_from_u8).map(|x| x as i16)?),
227 (2, 16) => Ok(reader.read_le_i16()?),
228 (n, _) if n > 2 => Err(Error::TooWide),
229 _ => Err(Error::Unsupported),
231 }
232 }
233}
234
235impl Sample for i32 {
236 fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()> {
237 match bits {
238 8 => Ok(writer.write_u8(u8_from_signed(narrow_to_i8(self)?))?),
239 16 => Ok(writer.write_le_i16(narrow_to_i16(self)?)?),
240 24 => Ok(writer.write_le_i24(narrow_to_i24(self)?)?),
241 32 => Ok(writer.write_le_i32(self)?),
242 _ => Err(Error::Unsupported),
243 }
244 }
245
246 #[inline(always)]
247 fn as_i16(&self) -> i16 {
248 *self as i16
249 }
250
251 fn read<R: io::Read>(reader: &mut R, fmt: SampleFormat, bytes: u16, bits: u16) -> Result<i32> {
252 if fmt != SampleFormat::Int {
253 return Err(Error::InvalidSampleFormat);
254 }
255 match (bytes, bits) {
256 (1, 8) => Ok(reader.read_u8().map(signed_from_u8).map(|x| x as i32)?),
257 (2, 16) => Ok(reader.read_le_i16().map(|x| x as i32)?),
258 (3, 24) => Ok(reader.read_le_i24()?),
259 (4, 32) => Ok(reader.read_le_i32()?),
260 (n, _) if n > 4 => Err(Error::TooWide),
261 _ => Err(Error::Unsupported),
263 }
264 }
265}
266
267impl Sample for f32 {
268 fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()> {
269 match bits {
270 32 => Ok(writer.write_le_f32(self)?),
271 _ => Err(Error::Unsupported),
272 }
273 }
274
275 fn as_i16(&self) -> i16 {
276 panic!("Calling as_i16 with an f32 is invalid.");
277 }
278
279 fn read<R: io::Read>(reader: &mut R, fmt: SampleFormat, bytes: u16, bits: u16) -> Result<Self> {
280 if fmt != SampleFormat::Float {
281 return Err(Error::InvalidSampleFormat);
282 }
283 match (bytes, bits) {
284 (4, 32) => Ok(reader.read_le_f32()?),
285 (n, _) if n > 4 => Err(Error::TooWide),
286 _ => Err(Error::Unsupported),
287 }
288 }
289}
290
291#[derive(Clone, Copy, Debug, PartialEq, Eq)]
293pub enum SampleFormat {
294 Float,
299 Int,
301}
302
303#[derive(Clone, Copy, Debug, PartialEq, Eq)]
305pub struct WavSpec {
306 pub channels: u16,
308
309 pub sample_rate: u32,
313
314 pub bits_per_sample: u16,
318
319 pub sample_format: SampleFormat,
321}
322
323#[derive(Debug)]
325pub enum Error {
326 IoError(io::Error),
328 FormatError(&'static str),
330 TooWide,
337 UnfinishedSample,
339 Unsupported,
341 InvalidSampleFormat,
351}
352
353impl fmt::Display for Error {
354 fn fmt(&self, formatter: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
355 match *self {
356 Error::IoError(ref err) => err.fmt(formatter),
357 Error::FormatError(reason) => {
358 formatter.write_str("Ill-formed WAVE file: ")?;
359 formatter.write_str(reason)
360 }
361 Error::TooWide => {
362 formatter.write_str("The sample has more bits than the destination type.")
363 }
364 Error::UnfinishedSample => {
365 formatter.write_str(
366 "The number of samples written is not a multiple of the number of channels.")
367 }
368 Error::Unsupported => {
369 formatter.write_str("The wave format of the file is not supported.")
370 }
371 Error::InvalidSampleFormat => {
372 formatter.write_str("The sample format differs from the destination format.")
373 }
374 }
375 }
376}
377
378impl error::Error for Error {
379 #[allow(deprecated)]
380 fn description(&self) -> &str {
381 match *self {
382 Error::IoError(ref err) => err.description(),
383 Error::FormatError(reason) => reason,
384 Error::TooWide => "the sample has more bits than the destination type",
385 Error::UnfinishedSample => "the number of samples written is not a multiple of the number of channels",
386 Error::Unsupported => "the wave format of the file is not supported",
387 Error::InvalidSampleFormat => "the sample format differs from the destination format",
388 }
389 }
390
391 fn cause(&self) -> Option<&dyn error::Error> {
392 match *self {
393 Error::IoError(ref err) => Some(err),
394 Error::FormatError(_) => None,
395 Error::TooWide => None,
396 Error::UnfinishedSample => None,
397 Error::Unsupported => None,
398 Error::InvalidSampleFormat => None,
399 }
400 }
401}
402
403impl From<io::Error> for Error {
404 fn from(err: io::Error) -> Error {
405 Error::IoError(err)
406 }
407}
408
409pub type Result<T> = result::Result<T, Error>;
411
412const KSDATAFORMAT_SUBTYPE_PCM: [u8; 16] = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80,
423 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71];
424
425const KSDATAFORMAT_SUBTYPE_IEEE_FLOAT: [u8; 16] = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
427 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71];
428
429#[test]
430fn write_read_i16_is_lossless() {
431 let mut buffer = io::Cursor::new(Vec::new());
432 let write_spec = WavSpec {
433 channels: 2,
434 sample_rate: 44100,
435 bits_per_sample: 16,
436 sample_format: SampleFormat::Int,
437 };
438
439 {
440 let mut writer = WavWriter::new(&mut buffer, write_spec).unwrap();
441 for s in -1024_i16..1024 {
442 writer.write_sample(s).unwrap();
443 }
444 writer.finalize().unwrap();
445 }
446
447 {
448 buffer.set_position(0);
449 let mut reader = WavReader::new(&mut buffer).unwrap();
450 assert_eq!(write_spec, reader.spec());
451 assert_eq!(reader.len(), 2048);
452 for (expected, read) in (-1024_i16..1024).zip(reader.samples()) {
453 assert_eq!(expected, read.unwrap());
454 }
455 }
456}
457
458#[test]
459fn write_read_i16_via_sample_writer_is_lossless() {
460 let mut buffer = io::Cursor::new(Vec::new());
461 let write_spec = WavSpec {
462 channels: 2,
463 sample_rate: 44100,
464 bits_per_sample: 16,
465 sample_format: SampleFormat::Int,
466 };
467
468 {
469 let mut writer = WavWriter::new(&mut buffer, write_spec).unwrap();
470 {
471 {
472 let mut sample_writer = writer.get_i16_writer(1024);
473 for s in -1024_i16..0 {
474 sample_writer.write_sample(s);
475 }
476 sample_writer.flush().unwrap();
477 }
478
479 {
480 let mut sample_writer = writer.get_i16_writer(1024);
481 for s in 0i16..1024 {
482 sample_writer.write_sample_unchecked(s);
483 }
484 sample_writer.flush().unwrap();
485 }
486 }
487 writer.finalize().unwrap();
488 }
489
490 {
491 buffer.set_position(0);
492 let mut reader = WavReader::new(&mut buffer).unwrap();
493 assert_eq!(write_spec, reader.spec());
494 assert_eq!(reader.len(), 2048);
495 for (expected, read) in (-1024_i16..1024).zip(reader.samples()) {
496 assert_eq!(expected, read.unwrap());
497 }
498 }
499}
500
501#[test]
502fn write_read_i8_is_lossless() {
503 let mut buffer = io::Cursor::new(Vec::new());
504 let write_spec = WavSpec {
505 channels: 16,
506 sample_rate: 48000,
507 bits_per_sample: 8,
508 sample_format: SampleFormat::Int,
509 };
510
511 {
513 let mut writer = WavWriter::new(&mut buffer, write_spec).unwrap();
514 for s in -128_i16..127 + 1 {
516 writer.write_sample(s as i8).unwrap();
517 }
518 writer.finalize().unwrap();
519 }
520
521 {
523 buffer.set_position(0);
524 let mut reader = WavReader::new(&mut buffer).unwrap();
525 assert_eq!(write_spec, reader.spec());
526 assert_eq!(reader.len(), 256);
527 for (expected, read) in (-128_i16..127 + 1).zip(reader.samples()) {
528 assert_eq!(expected, read.unwrap());
529 }
530 }
531}
532
533#[test]
534fn write_read_i24_is_lossless() {
535 let mut buffer = io::Cursor::new(Vec::new());
536 let write_spec = WavSpec {
537 channels: 16,
538 sample_rate: 96000,
539 bits_per_sample: 24,
540 sample_format: SampleFormat::Int,
541 };
542
543 {
545 let mut writer = WavWriter::new(&mut buffer, write_spec).unwrap();
546 for s in -128_i32..127 + 1 {
547 writer.write_sample(s * 256 * 256).unwrap();
548 }
549 writer.finalize().unwrap();
550 }
551
552 {
555 buffer.set_position(0);
556 let mut reader = WavReader::new(&mut buffer).unwrap();
557 assert_eq!(write_spec, reader.spec());
558 assert_eq!(reader.len(), 256);
559 for (expected, read) in (-128_i32..127 + 1)
560 .map(|x| x * 256 * 256)
561 .zip(reader.samples()) {
562 assert_eq!(expected, read.unwrap());
563 }
564 }
565}
566#[test]
567fn write_read_f32_is_lossless() {
568 let mut buffer = io::Cursor::new(Vec::new());
569 let write_spec = WavSpec {
570 channels: 2,
571 sample_rate: 44100,
572 bits_per_sample: 32,
573 sample_format: SampleFormat::Float,
574 };
575
576 {
577 let mut writer = WavWriter::new(&mut buffer, write_spec).unwrap();
578 for s in 1_u32..257 {
579 writer.write_sample(1.0f32 / s as f32).unwrap();
580 }
581 writer.finalize().unwrap();
582 }
583
584 {
585 buffer.set_position(0);
586 let mut reader = WavReader::new(&mut buffer).unwrap();
587 assert_eq!(write_spec, reader.spec());
588 assert_eq!(reader.len(), 256);
589 for (expected, read) in (1..257)
590 .map(|x| 1.0_f32 / x as f32)
591 .zip(reader.samples()) {
592 assert_eq!(expected, read.unwrap());
593 }
594 }
595}
596
597#[test]
598#[should_panic]
599fn no_32_bps_for_float_sample_format_panics() {
600 let mut buffer = io::Cursor::new(Vec::new());
601 let write_spec = WavSpec {
602 channels: 2,
603 sample_rate: 44100,
604 bits_per_sample: 16, sample_format: SampleFormat::Float,
606 };
607
608 WavWriter::new(&mut buffer, write_spec).unwrap();
609}
610
611#[test]
612fn flush_should_produce_valid_file() {
613 use std::mem;
614 use std::io::Seek;
615
616 let mut buffer = io::Cursor::new(Vec::new());
617 let samples = &[2, 4, 5, 7, 11, 13];
618
619 {
620 let spec = WavSpec {
621 channels: 2,
622 sample_rate: 44100,
623 bits_per_sample: 16,
624 sample_format: SampleFormat::Int,
625 };
626 let mut writer = WavWriter::new(&mut buffer, spec).unwrap();
627
628 for &x in samples {
629 writer.write_sample(x).unwrap();
630 }
631
632 writer.flush().unwrap();
634
635 writer.write_sample(17).unwrap();
638 writer.write_sample(19).unwrap();
639
640 mem::forget(writer);
641 }
642
643 buffer.seek(io::SeekFrom::Start(0)).unwrap();
644
645 let mut reader = WavReader::new(&mut buffer).unwrap();
646 let read_samples: Vec<i16> = reader.samples()
647 .map(|r| r.unwrap())
648 .collect();
649
650 assert_eq!(&read_samples[..], &samples[..]);
652}
653
654#[test]
655fn new_append_should_append() {
656 use std::io::Seek;
657
658 let mut buffer = io::Cursor::new(Vec::new());
659 let samples = &[2, 5, 7, 11];
660 let spec = WavSpec {
661 channels: 2,
662 sample_rate: 44100,
663 bits_per_sample: 16,
664 sample_format: SampleFormat::Int,
665 };
666
667 {
669 let mut writer = WavWriter::new(&mut buffer, spec).unwrap();
670 for s in samples { writer.write_sample(*s).unwrap(); }
671 }
672
673 buffer.seek(io::SeekFrom::Start(0)).unwrap();
674
675 {
677 let mut writer = WavWriter::new_append(&mut buffer).unwrap();
678 assert_eq!(writer.spec(), spec);
679 for s in samples { writer.write_sample(*s).unwrap(); }
680 }
681
682 buffer.seek(io::SeekFrom::Start(0)).unwrap();
683
684 let mut reader = WavReader::new(&mut buffer).unwrap();
685 let read_samples: Vec<i16> = reader.samples()
686 .map(|r| r.unwrap())
687 .collect();
688
689 assert_eq!(&read_samples[..], &[2, 5, 7, 11, 2, 5, 7, 11]);
691}
692
693#[test]
694fn new_append_does_not_corrupt_files() {
695 use std::io::Read;
696 use std::fs;
697
698 let sample_files = [
699 "testsamples/pcmwaveformat-16bit-44100Hz-mono-extra.wav",
700 "testsamples/pcmwaveformat-16bit-44100Hz-mono.wav",
701 "testsamples/pcmwaveformat-8bit-44100Hz-mono.wav",
702 "testsamples/pop.wav",
703 "testsamples/waveformatex-16bit-44100Hz-mono-extra.wav",
704 "testsamples/waveformatex-16bit-44100Hz-mono.wav",
705 "testsamples/waveformatex-16bit-44100Hz-stereo.wav",
706 "testsamples/waveformatextensible-24bit-192kHz-mono.wav",
707 "testsamples/waveformatextensible-32bit-48kHz-stereo.wav",
708 "testsamples/nonstandard-01.wav",
709 "testsamples/waveformatex-8bit-11025Hz-mono.wav",
710 ];
711
712 for fname in &sample_files {
713 print!("testing {} ... ", fname);
714
715 let mut buffer = Vec::new();
716 let mut f = fs::File::open(fname).unwrap();
717 f.read_to_end(&mut buffer).unwrap();
718
719 let samples_orig: Vec<i32>;
720 let samples_after: Vec<i32>;
721
722 let mut cursor = io::Cursor::new(buffer);
724 {
725 let mut reader = WavReader::new(&mut cursor).unwrap();
726 samples_orig = reader.samples().map(|r| r.unwrap()).collect();
727 }
728 buffer = cursor.into_inner();
729
730 let mut cursor = io::Cursor::new(buffer);
732 {
733 let mut writer = WavWriter::new_append(&mut cursor).unwrap();
734 writer.write_sample(41_i8).unwrap();
735 writer.write_sample(43_i8).unwrap();
736 }
737 buffer = cursor.into_inner();
738
739 {
740 let cursor = io::Cursor::new(buffer);
741 let mut reader = WavReader::new(cursor)
742 .expect("Reading wav failed after append.");
743 samples_after = reader.samples().map(|r| r.unwrap()).collect();
744 }
745
746 assert_eq!(&samples_orig[..], &samples_after[..samples_orig.len()]);
747 assert_eq!(samples_after[samples_after.len() - 2], 41_i32);
748 assert_eq!(samples_after[samples_after.len() - 1], 43_i32);
749
750 println!("ok");
751 }
752}
753
754#[cfg(test)]
755fn assert_contents(fname: &str, expected: &[i16]) {
756 let mut reader = WavReader::open(fname).unwrap();
757 let samples: Vec<i16> = reader.samples().map(|s| s.unwrap()).collect();
758 assert_eq!(&samples[..], expected);
759}
760
761#[test]
762fn append_works_on_files() {
763 use std::fs;
764
765 let spec = WavSpec {
766 channels: 1,
767 sample_rate: 44100,
768 bits_per_sample: 16,
769 sample_format: SampleFormat::Int,
770 };
771
772 let mut writer = WavWriter::create("append.wav", spec).unwrap();
773 writer.write_sample(11_i16).unwrap();
774 writer.write_sample(13_i16).unwrap();
775 writer.write_sample(17_i16).unwrap();
776 writer.finalize().unwrap();
777
778 assert_contents("append.wav", &[11, 13, 17]);
779
780 let len = fs::metadata("append.wav").unwrap().len();
781
782 let mut appender = WavWriter::append("append.wav").unwrap();
783
784 appender.write_sample(19_i16).unwrap();
785 appender.write_sample(23_i16).unwrap();
786 appender.finalize().unwrap();
787
788 assert_eq!(fs::metadata("append.wav").unwrap().len(), len + 4);
791
792 assert_contents("append.wav", &[11, 13, 17, 19, 23]);
793}