1use std::fs::File;
153use std::io::{BufReader, BufWriter, ErrorKind, Read, Result, Seek, Write};
154use std::path::Path;
155
156pub mod open_wav;
157pub mod reader;
158pub mod wave_header;
159pub mod wave_reader;
160pub mod wave_writer;
161pub mod writer;
162
163mod assertions;
164mod constants;
165pub mod samples_by_channel;
166mod upconvert;
167
168use reader::ReadEx;
169use wave_header::*;
170use wave_reader::*;
171use wave_writer::*;
172use writer::WriteEx;
173
174pub fn read_wav_from_file_path(file_path: &Path) -> Result<OpenWavReader<BufReader<File>>> {
181 let file = File::open(file_path)?;
182 let reader = BufReader::new(file);
183
184 read_wav(reader)
185}
186
187pub fn read_wav<TReader: 'static + Read>(mut reader: TReader) -> Result<OpenWavReader<TReader>> {
193 reader.assert_str(
195 "RIFF",
196 ErrorKind::InvalidInput,
197 "Not a WAVE file (Missing RIFF Header)",
198 )?;
199 let _file_length = reader.read_u32()?;
200 reader.assert_str(
201 "WAVE",
202 ErrorKind::Unsupported,
203 "Not a WAVE file (Missing WAVE header)",
204 )?;
205
206 let mut subchunk_size = 0usize;
209 let header = WavHeader::from_reader(&mut reader, &mut subchunk_size)?;
210
211 OpenWavReader::new(reader, header, 20 + subchunk_size)
214}
215
216pub fn write_wav_to_file_path(file_path: &Path, header: WavHeader) -> Result<OpenWavWriter> {
328 let file = File::create(file_path)?;
329 let writer = BufWriter::new(file);
330
331 write_wav(writer, header)
332}
333
334pub fn write_wav<TWriter: 'static + Write + Seek>(
341 mut writer: TWriter,
342 header: WavHeader,
343) -> Result<OpenWavWriter> {
344 writer.write(b"RIFF WAVE")?;
346
347 WavHeader::to_writer(&mut writer, &header)?;
348
349 OpenWavWriter::new(writer, header)
350}
351
352#[cfg(test)]
353mod tests {
354 use std::fmt::Debug;
355 use std::i8;
356 use std::io::{Cursor, Take};
357
358 use tempfile::tempdir;
359
360 use super::*;
361 use crate::open_wav::OpenWav;
362 use crate::samples_by_channel::SamplesByChannel;
363 use crate::upconvert::{
364 INT_16_DIVIDE_FOR_FLOAT, INT_24_DIVIDE_FOR_FLOAT, INT_8_ADD_FOR_FLOAT_ABS,
365 INT_8_DIVIDE_FOR_FLOAT,
366 };
367
368 #[test]
369 fn open_sanity() {
370 let open_wav = read_wav_from_file_path(Path::new("test_data/short_float.wav")).unwrap();
371 assert_eq!(SampleFormat::Float, open_wav.sample_format());
372 assert_eq!(1, open_wav.num_channels());
373 assert_eq!(32, open_wav.bits_per_sample());
374 assert_eq!(48000, open_wav.sample_rate());
375 assert_eq!(1267, open_wav.len_samples());
376
377 let open_wav = read_wav_from_file_path(Path::new("test_data/short_24.wav")).unwrap();
378 assert_eq!(SampleFormat::Int24, open_wav.sample_format());
379 assert_eq!(1, open_wav.num_channels());
380 assert_eq!(24, open_wav.bits_per_sample());
381 assert_eq!(48000, open_wav.sample_rate());
382 assert_eq!(1267, open_wav.len_samples());
383
384 let open_wav = read_wav_from_file_path(Path::new("test_data/short_16.wav")).unwrap();
385 assert_eq!(SampleFormat::Int16, open_wav.sample_format());
386 assert_eq!(1, open_wav.num_channels());
387 assert_eq!(16, open_wav.bits_per_sample());
388 assert_eq!(48000, open_wav.sample_rate());
389 assert_eq!(1267, open_wav.len_samples());
390 }
391
392 #[test]
393 fn read_float_sanity() {
394 let open_wav = read_wav_from_file_path(Path::new("test_data/short_float.wav")).unwrap();
395 let wave_reader_float = open_wav.get_random_access_f32_reader().unwrap();
396 assert_eq!(
397 SampleFormat::Float,
398 wave_reader_float.info().sample_format()
399 );
400 assert_eq!(1, wave_reader_float.info().num_channels());
401 assert_eq!(32, wave_reader_float.info().bits_per_sample());
402 assert_eq!(48000, wave_reader_float.info().sample_rate());
403 assert_eq!(1267, wave_reader_float.info().len_samples());
404 }
405
406 #[test]
407 fn read_random_i8() {
408 read_random(
409 Path::new("test_data/short_8.wav"),
410 Box::new(|open_wav| open_wav.get_random_access_i8_reader()),
411 i8::from_le_bytes([0x7D]),
412 i8::from_le_bytes([0x7F]),
413 i8::from_le_bytes([0x7A]),
414 )
415 .unwrap();
416 }
417
418 #[test]
419 fn read_random_i8_as_i16() {
420 read_random(
421 Path::new("test_data/short_8.wav"),
422 Box::new(|open_wav| open_wav.get_random_access_i16_reader()),
423 32255,
424 32767,
425 31487,
426 )
427 .unwrap();
428 }
429
430 #[test]
431 fn read_random_i8_as_i24() {
432 read_random(
433 Path::new("test_data/short_8.wav"),
434 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
435 8257535,
436 8388607,
437 8060927,
438 )
439 .unwrap();
440 }
441
442 #[test]
443 fn read_random_i8_as_f32() {
444 read_random(
445 Path::new("test_data/short_8.wav"),
446 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
447 0.9843137,
448 1.0,
449 0.9607843,
450 )
451 .unwrap();
452 }
453
454 #[test]
455 fn read_random_i16() {
456 read_random(
457 Path::new("test_data/short_16.wav"),
458 Box::new(|open_wav| open_wav.get_random_access_i16_reader()),
459 i16::from_le_bytes([0x61, 0xFD]),
460 i16::from_le_bytes([0xF9, 0xFD]),
461 i16::from_le_bytes([0x9C, 0xFE]),
462 )
463 .unwrap();
464 }
465
466 #[test]
467 fn read_random_i16_as_i24() {
468 read_random(
469 Path::new("test_data/short_16.wav"),
470 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
471 -171776,
472 -132864,
473 -91136,
474 )
475 .unwrap();
476 }
477
478 #[test]
479 fn read_random_i16_as_f32() {
480 read_random(
481 Path::new("test_data/short_16.wav"),
482 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
483 -0.020462334,
484 -0.015823603,
485 -0.010849178,
486 )
487 .unwrap();
488 }
489
490 #[test]
491 fn read_random_i24() {
492 read_random(
493 Path::new("test_data/short_24.wav"),
494 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
495 i32::from_le_bytes([0x00, 0x2E, 0x61, 0xFD]) >> 8,
496 i32::from_le_bytes([0x00, 0xE7, 0xF8, 0xFD]) >> 8,
497 i32::from_le_bytes([0x00, 0x94, 0x9C, 0xFE]) >> 8,
498 )
499 .unwrap();
500 }
501
502 #[test]
503 fn read_random_i24_as_f32() {
504 read_random(
505 Path::new("test_data/short_24.wav"),
506 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
507 -0.020471752,
508 -0.015841544,
509 -0.010846555,
510 )
511 .unwrap();
512 }
513
514 #[test]
515 fn read_random_f32() {
516 read_random(
517 Path::new("test_data/short_float.wav"),
518 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
519 f32::from_le_bytes([0x6D, 0xB4, 0xA7, 0xBC]),
520 f32::from_le_bytes([0x02, 0xC6, 0x81, 0xBC]),
521 f32::from_le_bytes([0xA0, 0xB5, 0x31, 0xBC]),
522 )
523 .unwrap();
524 }
525
526 fn read_random<T: Debug + PartialEq>(
527 path: &Path,
528 get_random_access_reader: Box<
529 dyn FnOnce(OpenWavReader<BufReader<File>>) -> Result<RandomAccessWavReader<T>>,
530 >,
531 expected_sample_0: T,
532 expected_sample_1: T,
533 expected_sample_end: T,
534 ) -> Result<()> {
535 let open_wav = read_wav_from_file_path(path)?;
536 let mut wave_reader = get_random_access_reader(open_wav)?;
537
538 let actual_sample = wave_reader.read_sample(0)?;
539 assert_eq!(
540 expected_sample_0,
541 actual_sample.front_left.expect("Front left missing"),
542 "Wrong sample read at sample 0, channel 0"
543 );
544
545 let actual_sample = wave_reader.read_sample(1)?;
546 assert_eq!(
547 expected_sample_1,
548 actual_sample.front_left.expect("Front left missing"),
549 "Wrong sample read at sample 1, channel 0"
550 );
551
552 let actual_sample = wave_reader.read_sample(wave_reader.info().len_samples() - 1)?;
553 assert_eq!(
554 expected_sample_end,
555 actual_sample.front_left.expect("Front left missing"),
556 "Wrong sample read at sample 1266, channel 0"
557 );
558
559 Ok(())
560 }
561
562 #[test]
563 fn read_stream_f32_sanity() {
564 let file = File::open(Path::new("test_data/short_float.wav")).unwrap();
565 let reader = BufReader::new(file).take(u64::MAX); let open_wav = read_wav(reader).unwrap();
568 let wave_reader_float = open_wav.get_stream_f32_reader().unwrap();
569 assert_eq!(
570 SampleFormat::Float,
571 wave_reader_float.info().sample_format()
572 );
573 assert_eq!(1, wave_reader_float.info().num_channels());
574 assert_eq!(32, wave_reader_float.info().bits_per_sample());
575 assert_eq!(48000, wave_reader_float.info().sample_rate());
576 assert_eq!(1267, wave_reader_float.info().len_samples());
577 }
578
579 #[test]
580 fn read_stream_i8() {
581 read_stream(
582 Path::new("test_data/short_8.wav"),
583 Box::new(|open_wav| open_wav.get_stream_i8_reader()),
584 i8::from_le_bytes([0x7D]),
585 i8::from_le_bytes([0x7F]),
586 i8::from_le_bytes([0x7A]),
587 )
588 .unwrap();
589 }
590
591 #[test]
592 fn read_stream_i8_as_i16() {
593 read_stream(
594 Path::new("test_data/short_8.wav"),
595 Box::new(|open_wav| open_wav.get_stream_i16_reader()),
596 32255,
597 32767,
598 31487,
599 )
600 .unwrap();
601 }
602
603 #[test]
604 fn read_stream_i8_as_i24() {
605 read_stream(
606 Path::new("test_data/short_8.wav"),
607 Box::new(|open_wav| open_wav.get_stream_i24_reader()),
608 8257535,
609 8388607,
610 8060927,
611 )
612 .unwrap();
613 }
614
615 #[test]
616 fn read_stream_i8_as_f32() {
617 read_stream(
618 Path::new("test_data/short_8.wav"),
619 Box::new(|open_wav| open_wav.get_stream_f32_reader()),
620 0.9843137,
621 1.0,
622 0.9607843,
623 )
624 .unwrap();
625 }
626
627 #[test]
628 fn read_stream_i16() {
629 read_stream(
630 Path::new("test_data/short_16.wav"),
631 Box::new(|open_wav| open_wav.get_stream_i16_reader()),
632 i16::from_le_bytes([0x61, 0xFD]),
633 i16::from_le_bytes([0xF9, 0xFD]),
634 i16::from_le_bytes([0x9C, 0xFE]),
635 )
636 .unwrap();
637 }
638
639 #[test]
640 fn read_stream_i16_as_i24() {
641 read_stream(
642 Path::new("test_data/short_16.wav"),
643 Box::new(|open_wav| open_wav.get_stream_i24_reader()),
644 -171776,
645 -132864,
646 -91136,
647 )
648 .unwrap();
649 }
650
651 #[test]
652 fn read_stream_i16_as_f32() {
653 read_stream(
654 Path::new("test_data/short_16.wav"),
655 Box::new(|open_wav| open_wav.get_stream_f32_reader()),
656 -0.020462334,
657 -0.015823603,
658 -0.010849178,
659 )
660 .unwrap();
661 }
662
663 #[test]
664 fn read_stream_i24() {
665 read_stream(
666 Path::new("test_data/short_24.wav"),
667 Box::new(|open_wav| open_wav.get_stream_i24_reader()),
668 i32::from_le_bytes([0x00, 0x2E, 0x61, 0xFD]) >> 8,
669 i32::from_le_bytes([0x00, 0xE7, 0xF8, 0xFD]) >> 8,
670 i32::from_le_bytes([0x00, 0x94, 0x9C, 0xFE]) >> 8,
671 )
672 .unwrap();
673 }
674
675 #[test]
676 fn read_stream_i24_as_f32() {
677 read_stream(
678 Path::new("test_data/short_24.wav"),
679 Box::new(|open_wav| open_wav.get_stream_f32_reader()),
680 -0.020471752,
681 -0.015841544,
682 -0.010846555,
683 )
684 .unwrap();
685 }
686
687 #[test]
688 fn read_stream_f32() {
689 read_stream(
690 Path::new("test_data/short_float.wav"),
691 Box::new(|open_wav| open_wav.get_stream_f32_reader()),
692 f32::from_le_bytes([0x6D, 0xB4, 0xA7, 0xBC]),
693 f32::from_le_bytes([0x02, 0xC6, 0x81, 0xBC]),
694 f32::from_le_bytes([0xA0, 0xB5, 0x31, 0xBC]),
695 )
696 .unwrap();
697 }
698
699 fn read_stream<T: Debug + PartialEq + Default + Clone>(
700 path: &Path,
701 get_stream_reader: Box<
702 dyn FnOnce(OpenWavReader<Take<BufReader<File>>>) -> Result<StreamWavReader<T>>,
703 >,
704 expected_sample_0: T,
705 expected_sample_1: T,
706 expected_sample_end: T,
707 ) -> Result<()> {
708 let mut current_sample: usize = 0;
709
710 let file = File::open(path)?;
711 let reader = BufReader::new(file).take(u64::MAX);
713
714 let open_wav = read_wav(reader)?;
715
716 let iterator = get_stream_reader(open_wav)?.into_iter();
717 for samples_result in iterator {
718 let samples = samples_result?;
719
720 assert!(samples.front_left.is_some(), "Front left sample not read");
721 assert_eq!(None, samples.front_right, "Sample should not be read");
722 assert_eq!(None, samples.front_center, "Sample should not be read");
723 assert_eq!(None, samples.low_frequency, "Sample should not be read");
724 assert_eq!(None, samples.back_left, "Sample should not be read");
725 assert_eq!(None, samples.back_right, "Sample should not be read");
726 assert_eq!(
727 None, samples.front_left_of_center,
728 "Sample should not be read"
729 );
730 assert_eq!(
731 None, samples.front_right_of_center,
732 "Sample should not be read"
733 );
734 assert_eq!(None, samples.back_center, "Sample should not be read");
735 assert_eq!(None, samples.side_left, "Sample should not be read");
736 assert_eq!(None, samples.side_right, "Sample should not be read");
737 assert_eq!(None, samples.top_center, "Sample should not be read");
738 assert_eq!(None, samples.top_front_left, "Sample should not be read");
739 assert_eq!(None, samples.top_front_center, "Sample should not be read");
740 assert_eq!(None, samples.top_front_right, "Sample should not be read");
741 assert_eq!(None, samples.top_back_left, "Sample should not be read");
742 assert_eq!(None, samples.top_back_center, "Sample should not be read");
743 assert_eq!(None, samples.top_back_right, "Sample should not be read");
744
745 if current_sample == 0 {
746 assert_eq!(
747 expected_sample_0,
748 samples.front_left.unwrap(),
749 "Wrong sample read at sample 0, channel 0"
750 );
751 } else if current_sample == 1 {
752 assert_eq!(
753 expected_sample_1,
754 samples.front_left.unwrap(),
755 "Wrong sample read at sample 1, channel 0"
756 );
757 } else if current_sample == 1266 {
758 assert_eq!(
759 expected_sample_end,
760 samples.front_left.unwrap(),
761 "Wrong sample read at sample 1266, channel 0"
762 );
763 }
764
765 current_sample += 1;
766 }
767
768 assert_eq!(1267, current_sample, "Wrong number of samples read");
769
770 Ok(())
771 }
772
773 fn test_with_file(file_test_callback: Box<dyn FnOnce(&Path) -> Result<()>>) {
774 let temp_dir = tempdir().unwrap();
775
776 {
777 let path = temp_dir.path().join("tempwav.wav");
778 file_test_callback(&path).unwrap();
779 }
780 }
781
782 #[test]
783 fn write_sanity() {
784 test_with_file(Box::new(|path| {
785 let header = WavHeader {
786 sample_format: SampleFormat::Float,
787 channels: Channels::new()
788 .front_left()
789 .front_right()
790 .front_center()
791 .low_frequency()
792 .back_left()
793 .back_right(),
794 sample_rate: 96000,
795 };
796 let mut open_wav = write_wav_to_file_path(path, header)?;
797
798 assert_eq!(
799 SampleFormat::Float,
800 open_wav.sample_format(),
801 "Wrong sample format"
802 );
803 assert_eq!(6, open_wav.num_channels(), "Wrong channels");
804 assert_eq!(96000, open_wav.sample_rate(), "Wrong sampling rate");
805 assert_eq!(4, open_wav.bytes_per_sample(), "Wrong bytes per sample");
806 assert_eq!(32, open_wav.bits_per_sample(), "Wrong bits per sample");
807
808 open_wav.flush()?;
809
810 let open_wav = read_wav_from_file_path(path)?;
811
812 assert_eq!(
813 SampleFormat::Float,
814 open_wav.sample_format(),
815 "Wrong sample format when reading"
816 );
817 assert_eq!(6, open_wav.num_channels(), "Wrong channels when reading");
818 assert_eq!(
819 96000,
820 open_wav.sample_rate(),
821 "Wrong sampling rate when reading"
822 );
823 assert_eq!(
824 4,
825 open_wav.bytes_per_sample(),
826 "Wrong bytes per sample when reading"
827 );
828 assert_eq!(
829 32,
830 open_wav.bits_per_sample(),
831 "Wrong bits per sample when reading"
832 );
833 assert_eq!(0, open_wav.len_samples(), "Wrong length when reading");
834
835 Ok(())
836 }));
837 }
838
839 #[test]
840 fn write_random_i8() {
841 write_random(
842 SampleFormat::Int8,
843 Box::new(|open_wav| open_wav.get_random_access_i8_reader()),
844 Box::new(|sample_value| sample_value),
845 Box::new(|open_wav| open_wav.get_random_access_i8_writer()),
846 Box::new(|sample_value| sample_value as i8),
847 );
848 }
849
850 #[test]
851 fn write_random_i8_as_i16() {
852 write_random(
853 SampleFormat::Int16,
854 Box::new(|open_wav| open_wav.get_random_access_i16_reader()),
856 Box::new(|sample_value| {
857 let sample_value = sample_value as i32;
858 if sample_value > 0 {
859 return (((sample_value + 1) / 256) - 1) as i8;
860 } else {
861 return (sample_value / 256) as i8;
863 }
864 }),
865 Box::new(|open_wav| open_wav.get_random_access_i8_writer()),
866 Box::new(|sample_value| sample_value as i8),
867 );
868 }
869
870 #[test]
871 fn write_random_i8_as_i24() {
872 write_random(
873 SampleFormat::Int24,
874 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
876 Box::new(|sample_value| {
877 if sample_value > 0 {
878 return (((sample_value + 1) / 65536) - 1) as i8;
879 } else {
880 return (sample_value / 65536) as i8;
882 }
883 }),
884 Box::new(|open_wav| open_wav.get_random_access_i8_writer()),
885 Box::new(|sample_value| sample_value as i8),
886 );
887 }
888
889 #[test]
890 fn write_random_i8_as_f32() {
891 write_random(
892 SampleFormat::Float,
893 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
894 Box::new(|sample_value| {
895 let sample_int_8_abs = (sample_value + 1.0) * INT_8_DIVIDE_FOR_FLOAT;
896 let sample_int_8_as_float = sample_int_8_abs - INT_8_ADD_FOR_FLOAT_ABS;
897 return sample_int_8_as_float as i8;
898 }),
899 Box::new(|open_wav| open_wav.get_random_access_i8_writer()),
900 Box::new(|sample_value| sample_value as i8),
901 );
902 }
903
904 #[test]
905 fn write_random_i16() {
906 write_random(
907 SampleFormat::Int16,
908 Box::new(|open_wav| open_wav.get_random_access_i16_reader()),
909 Box::new(|sample_value| sample_value),
910 Box::new(|open_wav| open_wav.get_random_access_i16_writer()),
911 Box::new(|sample_value| sample_value as i16),
912 );
913 }
914
915 #[test]
916 fn write_random_i16_as_i24() {
917 write_random(
918 SampleFormat::Int24,
919 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
921 Box::new(|sample_value| {
922 if sample_value > 0 {
923 return (((sample_value + 1) / 256) - 1) as i16;
924 } else {
925 return (sample_value / 256) as i16;
927 }
928 }),
929 Box::new(|open_wav| open_wav.get_random_access_i16_writer()),
930 Box::new(|sample_value| sample_value as i16),
931 );
932 }
933
934 #[test]
935 fn write_random_i16_as_f32() {
936 write_random(
937 SampleFormat::Float,
938 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
939 Box::new(|sample_value| (sample_value * INT_16_DIVIDE_FOR_FLOAT) as i16),
940 Box::new(|open_wav| open_wav.get_random_access_i16_writer()),
941 Box::new(|sample_value| sample_value as i16),
942 );
943 }
944
945 #[test]
946 fn write_random_i24() {
947 write_random(
948 SampleFormat::Int24,
949 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
950 Box::new(|sample_value| sample_value),
951 Box::new(|open_wav| open_wav.get_random_access_i24_writer()),
952 Box::new(|sample_value| sample_value as i32),
953 );
954 }
955
956 #[test]
957 fn write_random_i24_as_f32() {
958 write_random(
959 SampleFormat::Float,
960 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
961 Box::new(|sample_value| (sample_value * INT_24_DIVIDE_FOR_FLOAT - 0.5) as i32),
962 Box::new(|open_wav| open_wav.get_random_access_i24_writer()),
963 Box::new(|sample_value| sample_value as i32),
964 );
965 }
966
967 #[test]
968 fn write_random_f32() {
969 write_random(
970 SampleFormat::Float,
971 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
972 Box::new(|sample_value| sample_value),
973 Box::new(|open_wav| open_wav.get_random_access_f32_writer()),
974 Box::new(|sample_value| sample_value as f32),
975 );
976 }
977
978 fn write_random<T: Debug + PartialEq + 'static, TFile: Debug + PartialEq + 'static>(
979 sample_format: SampleFormat,
980 get_random_access_reader: Box<
981 dyn FnOnce(OpenWavReader<BufReader<File>>) -> Result<RandomAccessWavReader<TFile>>,
982 >,
983 convert_sample_to_read: Box<dyn Fn(TFile) -> T>,
984 get_random_access_writer: Box<
985 dyn FnOnce(OpenWavWriter) -> Result<RandomAccessWavWriter<T>>,
986 >,
987 convert_sample_to_write: Box<dyn Fn(i32) -> T>,
988 ) {
989 test_with_file(Box::new(move |path| {
990 let header = WavHeader {
991 sample_format,
992 channels: Channels {
993 front_left: true,
994 front_right: true,
995 front_center: true,
996 low_frequency: true,
997 back_left: true,
998 back_right: true,
999 front_left_of_center: true,
1000 front_right_of_center: true,
1001 back_center: true,
1002 side_left: true,
1003 side_right: true,
1004 top_center: true,
1005 top_front_left: true,
1006 top_front_center: true,
1007 top_front_right: true,
1008 top_back_left: true,
1009 top_back_center: true,
1010 top_back_right: true,
1011 },
1012 sample_rate: 96000,
1013 };
1014 let open_wav = write_wav_to_file_path(path, header)?;
1015 let mut writer = get_random_access_writer(open_wav)?;
1016
1017 for sample_inv in 0..100usize {
1018 let sample = 99 - sample_inv;
1019 let sample_value = (sample as i32) * 18;
1020 let samples_by_channel = SamplesByChannel::<T> {
1021 front_left: Some(convert_sample_to_write(sample_value + 0i32)),
1022 front_right: Some(convert_sample_to_write(sample_value + 1)),
1023 front_center: Some(convert_sample_to_write(sample_value + 2)),
1024 low_frequency: Some(convert_sample_to_write(sample_value + 3)),
1025 back_left: Some(convert_sample_to_write(sample_value + 4)),
1026 back_right: Some(convert_sample_to_write(sample_value + 5)),
1027 front_left_of_center: Some(convert_sample_to_write(sample_value + 6)),
1028 front_right_of_center: Some(convert_sample_to_write(sample_value + 7)),
1029 back_center: Some(convert_sample_to_write(sample_value + 8)),
1030 side_left: Some(convert_sample_to_write(sample_value + 9)),
1031 side_right: Some(convert_sample_to_write(sample_value + 10)),
1032 top_center: Some(convert_sample_to_write(sample_value + 11)),
1033 top_front_left: Some(convert_sample_to_write(sample_value + 12)),
1034 top_front_center: Some(convert_sample_to_write(sample_value + 13)),
1035 top_front_right: Some(convert_sample_to_write(sample_value + 14)),
1036 top_back_left: Some(convert_sample_to_write(sample_value + 15)),
1037 top_back_center: Some(convert_sample_to_write(sample_value + 16)),
1038 top_back_right: Some(convert_sample_to_write(sample_value + 17)),
1039 };
1040 writer.write_samples(sample, samples_by_channel)?;
1041 }
1042
1043 writer.flush()?;
1044
1045 let open_wav = read_wav_from_file_path(path)?;
1046 assert_eq!(100, open_wav.len_samples(), "Wrong length of samples");
1047
1048 let mut reader = get_random_access_reader(open_wav)?;
1049
1050 for sample in 0..100usize {
1051 let samples_by_channel = reader.read_sample(sample)?;
1052
1053 assert_eq!(
1054 convert_sample_to_write((sample as i32) * 18 + (0 as i32)),
1055 convert_sample_to_read(samples_by_channel.front_left.expect("front_left")),
1056 "Wrong sample read at {sample}, channel front_left"
1057 );
1058 assert_eq!(
1059 convert_sample_to_write((sample as i32) * 18 + (1 as i32)),
1060 convert_sample_to_read(samples_by_channel.front_right.expect("front_right")),
1061 "Wrong sample read at {sample}, channel front_right"
1062 );
1063 assert_eq!(
1064 convert_sample_to_write((sample as i32) * 18 + (2 as i32)),
1065 convert_sample_to_read(samples_by_channel.front_center.expect("front_center")),
1066 "Wrong sample read at {sample}, channel front_center"
1067 );
1068 assert_eq!(
1069 convert_sample_to_write((sample as i32) * 18 + (3 as i32)),
1070 convert_sample_to_read(
1071 samples_by_channel.low_frequency.expect("low_frequency")
1072 ),
1073 "Wrong sample read at {sample}, channel low_frequency"
1074 );
1075 assert_eq!(
1076 convert_sample_to_write((sample as i32) * 18 + (4 as i32)),
1077 convert_sample_to_read(samples_by_channel.back_left.expect("back_left")),
1078 "Wrong sample read at {sample}, channel back_left"
1079 );
1080 assert_eq!(
1081 convert_sample_to_write((sample as i32) * 18 + (5 as i32)),
1082 convert_sample_to_read(samples_by_channel.back_right.expect("back_right")),
1083 "Wrong sample read at {sample}, channel back_right"
1084 );
1085 assert_eq!(
1086 convert_sample_to_write((sample as i32) * 18 + (6 as i32)),
1087 convert_sample_to_read(
1088 samples_by_channel
1089 .front_left_of_center
1090 .expect("front_left_of_center")
1091 ),
1092 "Wrong sample read at {sample}, channel front_left_of_center"
1093 );
1094 assert_eq!(
1095 convert_sample_to_write((sample as i32) * 18 + (7 as i32)),
1096 convert_sample_to_read(
1097 samples_by_channel
1098 .front_right_of_center
1099 .expect("front_right_of_center")
1100 ),
1101 "Wrong sample read at {sample}, channel front_right_of_center"
1102 );
1103 assert_eq!(
1104 convert_sample_to_write((sample as i32) * 18 + (8 as i32)),
1105 convert_sample_to_read(samples_by_channel.back_center.expect("back_center")),
1106 "Wrong sample read at {sample}, channel back_center"
1107 );
1108 assert_eq!(
1109 convert_sample_to_write((sample as i32) * 18 + (9 as i32)),
1110 convert_sample_to_read(samples_by_channel.side_left.expect("side_left")),
1111 "Wrong sample read at {sample}, channel side_left"
1112 );
1113 assert_eq!(
1114 convert_sample_to_write((sample as i32) * 18 + (10 as i32)),
1115 convert_sample_to_read(samples_by_channel.side_right.expect("side_right")),
1116 "Wrong sample read at {sample}, channel side_right"
1117 );
1118 assert_eq!(
1119 convert_sample_to_write((sample as i32) * 18 + (11 as i32)),
1120 convert_sample_to_read(samples_by_channel.top_center.expect("top_center")),
1121 "Wrong sample read at {sample}, channel top_center"
1122 );
1123 assert_eq!(
1124 convert_sample_to_write((sample as i32) * 18 + (12 as i32)),
1125 convert_sample_to_read(
1126 samples_by_channel.top_front_left.expect("top_front_left")
1127 ),
1128 "Wrong sample read at {sample}, channel top_front_left"
1129 );
1130 assert_eq!(
1131 convert_sample_to_write((sample as i32) * 18 + (13 as i32)),
1132 convert_sample_to_read(
1133 samples_by_channel
1134 .top_front_center
1135 .expect("top_front_center")
1136 ),
1137 "Wrong sample read at {sample}, channel top_front_center"
1138 );
1139 assert_eq!(
1140 convert_sample_to_write((sample as i32) * 18 + (14 as i32)),
1141 convert_sample_to_read(
1142 samples_by_channel.top_front_right.expect("top_front_right")
1143 ),
1144 "Wrong sample read at {sample}, channel top_front_right"
1145 );
1146 assert_eq!(
1147 convert_sample_to_write((sample as i32) * 18 + (15 as i32)),
1148 convert_sample_to_read(
1149 samples_by_channel.top_back_left.expect("top_back_left")
1150 ),
1151 "Wrong sample read at {sample}, channel top_back_left"
1152 );
1153 assert_eq!(
1154 convert_sample_to_write((sample as i32) * 18 + (16 as i32)),
1155 convert_sample_to_read(
1156 samples_by_channel.top_back_center.expect("top_back_center")
1157 ),
1158 "Wrong sample read at {sample}, channel top_back_center"
1159 );
1160 assert_eq!(
1161 convert_sample_to_write((sample as i32) * 18 + (17 as i32)),
1162 convert_sample_to_read(
1163 samples_by_channel.top_back_right.expect("top_back_right")
1164 ),
1165 "Wrong sample read at {sample}, channel top_back_right"
1166 );
1167 }
1168
1169 Ok(())
1170 }));
1171 }
1172
1173 #[test]
1174 fn write_random_max_samples() {
1175 test_with_file(Box::new(move |_path| {
1176 let header = WavHeader {
1177 sample_format: SampleFormat::Int8,
1178 channels: Channels {
1179 front_left: false,
1180 front_right: false,
1181 front_center: true,
1182 low_frequency: false,
1183 back_left: false,
1184 back_right: false,
1185 front_left_of_center: false,
1186 front_right_of_center: false,
1187 back_center: false,
1188 side_left: false,
1189 side_right: false,
1190 top_center: false,
1191 top_front_left: false,
1192 top_front_center: false,
1193 top_front_right: false,
1194 top_back_left: false,
1195 top_back_center: false,
1196 top_back_right: false,
1197 },
1198 sample_rate: 96000,
1199 };
1200
1201 let buffer: Vec<u8> = Vec::new();
1203 let cursor = Cursor::new(buffer);
1204 let open_wav = OpenWavWriter::new_max_samples(cursor, header, 1)?;
1205 let mut writer = open_wav.get_random_access_i8_writer()?;
1206
1207 let samples_by_channel = SamplesByChannel::<i8> {
1208 front_left: None,
1209 front_right: None,
1210 front_center: Some(1),
1211 low_frequency: None,
1212 back_left: None,
1213 back_right: None,
1214 front_left_of_center: None,
1215 front_right_of_center: None,
1216 back_center: None,
1217 side_left: None,
1218 side_right: None,
1219 top_center: None,
1220 top_front_left: None,
1221 top_front_center: None,
1222 top_front_right: None,
1223 top_back_left: None,
1224 top_back_center: None,
1225 top_back_right: None,
1226 };
1227 writer.write_samples(0, samples_by_channel.clone())?;
1228
1229 let err = writer
1230 .write_samples(1, samples_by_channel.clone())
1231 .expect_err("Writing at the max length should fail");
1232
1233 assert_eq!(ErrorKind::Unsupported, err.kind());
1234
1235 let err = writer
1236 .write_samples(2, samples_by_channel)
1237 .expect_err("Writing beyond the max length should fail");
1238
1239 assert_eq!(ErrorKind::Unsupported, err.kind());
1240
1241 Ok(())
1242 }));
1243 }
1244
1245 #[test]
1246 fn write_stream_i8() {
1247 write_stream(
1248 Path::new("test_data/short_8.wav"),
1249 SampleFormat::Int8,
1250 Box::new(|open_wav| open_wav.get_stream_i8_reader()),
1251 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i8(read_samples_iter)),
1252 Box::new(|open_wav| open_wav.get_random_access_i8_reader()),
1253 )
1254 }
1255
1256 #[test]
1257 fn write_stream_i8_as_i16() {
1258 write_stream(
1259 Path::new("test_data/short_8.wav"),
1260 SampleFormat::Int16,
1261 Box::new(|open_wav| open_wav.get_stream_i8_reader()),
1262 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i8(read_samples_iter)),
1263 Box::new(|open_wav| open_wav.get_random_access_i16_reader()),
1264 )
1265 }
1266
1267 #[test]
1268 fn write_stream_i8_as_i24() {
1269 write_stream(
1270 Path::new("test_data/short_8.wav"),
1271 SampleFormat::Int24,
1272 Box::new(|open_wav| open_wav.get_stream_i8_reader()),
1273 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i8(read_samples_iter)),
1274 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
1275 )
1276 }
1277
1278 #[test]
1279 fn write_stream_i8_as_f32() {
1280 write_stream(
1281 Path::new("test_data/short_8.wav"),
1282 SampleFormat::Float,
1283 Box::new(|open_wav| open_wav.get_stream_i8_reader()),
1284 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i8(read_samples_iter)),
1285 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
1286 )
1287 }
1288
1289 #[test]
1290 fn write_stream_i16() {
1291 write_stream(
1292 Path::new("test_data/short_16.wav"),
1293 SampleFormat::Int16,
1294 Box::new(|open_wav| open_wav.get_stream_i16_reader()),
1295 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i16(read_samples_iter)),
1296 Box::new(|open_wav| open_wav.get_random_access_i16_reader()),
1297 )
1298 }
1299
1300 #[test]
1301 fn write_stream_i16_as_i24() {
1302 write_stream(
1303 Path::new("test_data/short_16.wav"),
1304 SampleFormat::Int24,
1305 Box::new(|open_wav| open_wav.get_stream_i16_reader()),
1306 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i16(read_samples_iter)),
1307 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
1308 )
1309 }
1310
1311 #[test]
1312 fn write_stream_i16_as_f32() {
1313 write_stream(
1314 Path::new("test_data/short_16.wav"),
1315 SampleFormat::Float,
1316 Box::new(|open_wav| open_wav.get_stream_i16_reader()),
1317 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i16(read_samples_iter)),
1318 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
1319 )
1320 }
1321
1322 #[test]
1323 fn write_stream_i24() {
1324 write_stream(
1325 Path::new("test_data/short_24.wav"),
1326 SampleFormat::Int24,
1327 Box::new(|open_wav| open_wav.get_stream_i24_reader()),
1328 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i24(read_samples_iter)),
1329 Box::new(|open_wav| open_wav.get_random_access_i24_reader()),
1330 )
1331 }
1332
1333 #[test]
1334 fn write_stream_i24_as_f32() {
1335 write_stream(
1336 Path::new("test_data/short_24.wav"),
1337 SampleFormat::Float,
1338 Box::new(|open_wav| open_wav.get_stream_i24_reader()),
1339 Box::new(|open_wav, read_samples_iter| open_wav.write_all_i24(read_samples_iter)),
1340 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
1341 )
1342 }
1343
1344 #[test]
1345 fn write_stream_f32() {
1346 write_stream(
1347 Path::new("test_data/short_float.wav"),
1348 SampleFormat::Float,
1349 Box::new(|open_wav| open_wav.get_stream_f32_reader()),
1350 Box::new(|open_wav, read_samples_iter| open_wav.write_all_f32(read_samples_iter)),
1351 Box::new(|open_wav| open_wav.get_random_access_f32_reader()),
1352 )
1353 }
1354
1355 fn write_stream<
1356 T: Debug + PartialEq + Default + Clone + 'static,
1357 TFile: Debug + PartialEq + Default + Clone + 'static,
1358 >(
1359 read_path: &Path,
1360 sample_format: SampleFormat,
1361 get_stream_reader: Box<
1362 dyn FnOnce(OpenWavReader<BufReader<File>>) -> Result<StreamWavReader<T>>,
1363 >,
1364 write_all: Box<dyn FnOnce(OpenWavWriter, StreamWavReaderIterator<T>) -> Result<()>>,
1365 get_random_access_reader: Box<
1366 dyn Fn(OpenWavReader<BufReader<File>>) -> Result<RandomAccessWavReader<TFile>>,
1367 >,
1368 ) {
1369 let read_path_buf = read_path.to_path_buf();
1370
1371 test_with_file(Box::new(move |path| {
1372 let read_path = read_path_buf.as_path();
1373 let source_wav = read_wav_from_file_path(read_path)?;
1374
1375 let header = WavHeader {
1376 sample_format,
1377 channels: source_wav.channels().clone(),
1378 sample_rate: source_wav.sample_rate(),
1379 };
1380 let open_wav = write_wav_to_file_path(path, header)?;
1381
1382 let read_samples_iter = get_stream_reader(source_wav)?.into_iter();
1383 write_all(open_wav, read_samples_iter)?;
1384
1385 let expected_wav = read_wav_from_file_path(read_path)?;
1386 let actual_wav = read_wav_from_file_path(path)?;
1387
1388 assert_eq!(expected_wav.num_channels(), actual_wav.num_channels());
1389 assert_eq!(expected_wav.len_samples(), actual_wav.len_samples());
1390
1391 let len_samples = expected_wav.len_samples();
1392
1393 let mut expected_wav_reader = get_random_access_reader(expected_wav)?;
1394 let mut actual_wav_reader = get_random_access_reader(actual_wav)?;
1395
1396 for sample_ctr in 0..len_samples {
1397 let expected_samples = expected_wav_reader.read_sample(sample_ctr)?;
1398 let actual_samples = actual_wav_reader.read_sample(sample_ctr)?;
1399
1400 assert_eq!(
1401 expected_samples, actual_samples,
1402 "Wrong value for sample {sample_ctr}"
1403 );
1404 }
1405
1406 Ok(())
1407 }));
1408 }
1409
1410 #[test]
1411 fn write_stream_max_samples() {
1412 test_with_file(Box::new(move |_path| {
1413 let header = WavHeader {
1414 sample_format: SampleFormat::Int8,
1415 channels: Channels {
1416 front_left: false,
1417 front_right: false,
1418 front_center: true,
1419 low_frequency: false,
1420 back_left: false,
1421 back_right: false,
1422 front_left_of_center: false,
1423 front_right_of_center: false,
1424 back_center: false,
1425 side_left: false,
1426 side_right: false,
1427 top_center: false,
1428 top_front_left: false,
1429 top_front_center: false,
1430 top_front_right: false,
1431 top_back_left: false,
1432 top_back_center: false,
1433 top_back_right: false,
1434 },
1435 sample_rate: 96000,
1436 };
1437
1438 let samples_by_channel = SamplesByChannel::<i8> {
1439 front_left: None,
1440 front_right: None,
1441 front_center: Some(1),
1442 low_frequency: None,
1443 back_left: None,
1444 back_right: None,
1445 front_left_of_center: None,
1446 front_right_of_center: None,
1447 back_center: None,
1448 side_left: None,
1449 side_right: None,
1450 top_center: None,
1451 top_front_left: None,
1452 top_front_center: None,
1453 top_front_right: None,
1454 top_back_left: None,
1455 top_back_center: None,
1456 top_back_right: None,
1457 };
1458
1459 let buffer: Vec<u8> = Vec::new();
1461 let cursor = Cursor::new(buffer);
1462 let open_wav = OpenWavWriter::new_max_samples(cursor, header.clone(), 1)?;
1463 let samples = vec![Ok(samples_by_channel.clone())];
1464 open_wav.write_all_i8(samples.into_iter())?;
1465
1466 let buffer: Vec<u8> = Vec::new();
1468 let cursor = Cursor::new(buffer);
1469 let open_wav = OpenWavWriter::new_max_samples(cursor, header.clone(), 1)?;
1470 let samples = vec![
1471 Ok(samples_by_channel.clone()),
1472 Ok(samples_by_channel.clone()),
1473 ];
1474 let err = open_wav
1475 .write_all_i8(samples.into_iter())
1476 .expect_err("Should not be able to exceed the supported file length");
1477 assert_eq!(ErrorKind::Unsupported, err.kind());
1478
1479 let buffer: Vec<u8> = Vec::new();
1481 let cursor = Cursor::new(buffer);
1482 let open_wav = OpenWavWriter::new_max_samples(cursor, header, 1)?;
1483 let samples = vec![
1484 Ok(samples_by_channel.clone()),
1485 Ok(samples_by_channel.clone()),
1486 Ok(samples_by_channel),
1487 ];
1488 let err = open_wav
1489 .write_all_i8(samples.into_iter())
1490 .expect_err("Should not be able to exceed the supported file length");
1491 assert_eq!(ErrorKind::Unsupported, err.kind());
1492
1493 Ok(())
1494 }));
1495 }
1496}