From e0f075a912f125091f0284b90d952e23dcb42eb7 Mon Sep 17 00:00:00 2001 From: sagudev Date: Sun, 23 Jan 2022 13:37:13 +0100 Subject: [PATCH] Add testing against hound --- Cargo.toml | 2 +- src/iff/wav/properties.rs | 41 +++++++++++++++++++--------------- tests/hound.rs | 46 +++++++++++++++++++++++++++++---------- 3 files changed, 59 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 51b60a96..d9f80eab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ criterion = { version = "0.3.5", features = ["html_reports"] } tempfile = "3.3.0" # tag_writer example structopt = { version = "0.3.26", default-features = false } -hound = {git="https://github.com/ruuda/hound.git", branch="master"} +hound = { git = "https://github.com/ruuda/hound.git", rev = "02e66effb33683dd6acb92df792683ee46ad6a59" } [lib] bench = false diff --git a/src/iff/wav/properties.rs b/src/iff/wav/properties.rs index d173b8be..739422e2 100644 --- a/src/iff/wav/properties.rs +++ b/src/iff/wav/properties.rs @@ -128,25 +128,29 @@ pub(super) fn read_properties( let bits_per_sample = fmt.read_u16::()?; let bytes_per_sample = block_align / u16::from(channels); - // We allow bits_per_sample to be less than bytes_per_sample so that - // we can support things such as 24 bit samples in 4 byte containers. - if Some(bits_per_sample) > bytes_per_sample.checked_mul(8) { - return Err(LoftyError::Wav("sample bits exceeds size of sample")); - } + let mut bit_depth = if bits_per_sample > 0 { + bits_per_sample as u8 + } else { + (bytes_per_sample * 8) as u8 + }; if format_tag == EXTENSIBLE { - if fmt.len() < 40 { + if fmt.len() + 16 < 40 { return Err(LoftyError::Wav( "Extensible format identified, invalid \"fmt \" chunk size found (< 40)", )); } - // Skip 8 bytes // cbSize (Size of extra format information) (2) + let _cb_size = fmt.read_u16::()?; // Valid bits per sample (2) + let valid_bits_per_sample = fmt.read_u16::()?; // Channel mask (4) - fmt.read_u64::()?; + let _channel_mask = fmt.read_u32::()?; + if valid_bits_per_sample > 0 { + bit_depth = valid_bits_per_sample as u8; + } format_tag = fmt.read_u16::()?; } @@ -166,15 +170,18 @@ pub(super) fn read_properties( let (duration, overall_bitrate, audio_bitrate) = if sample_rate > 0 && total_samples > 0 { let length = (u64::from(total_samples) * 1000) / u64::from(sample_rate); + if length == 0 { + (Duration::from_secs(0), 0, 0) + } else { + let overall_bitrate = ((file_length * 8) / length) as u32; + let audio_bitrate = (u64::from(stream_len * 8) / length) as u32; - let overall_bitrate = ((file_length * 8) / length) as u32; - let audio_bitrate = (u64::from(stream_len * 8) / length) as u32; - - ( - Duration::from_millis(length), - overall_bitrate, - audio_bitrate, - ) + ( + Duration::from_millis(length), + overall_bitrate, + audio_bitrate, + ) + } } else if bytes_per_second > 0 { let length = (u64::from(stream_len) * 1000) / u64::from(bytes_per_second); @@ -200,7 +207,7 @@ pub(super) fn read_properties( overall_bitrate, audio_bitrate, sample_rate, - bit_depth: (bytes_per_sample * 8) as u8, + bit_depth, channels, }) } diff --git a/tests/hound.rs b/tests/hound.rs index 16241fee..6309a52b 100644 --- a/tests/hound.rs +++ b/tests/hound.rs @@ -1,15 +1,16 @@ -use std::{ - fs::{self, File}, - path::Path, -}; +use std::fs; +use std::fs::File; +use std::path::Path; use hound::WavReader; -use lofty::{iff::WavFile, AudioFile}; +use lofty::iff::WavFile; +use lofty::AudioFile; +use lofty::Result; -fn get_properties(path: &Path) -> ::Properties { +fn get_properties(path: &Path) -> Result<::Properties> { let mut f = File::open(path).unwrap(); - let wav_file = WavFile::read_from(&mut f, true).unwrap(); - *wav_file.properties() + let wav_file = WavFile::read_from(&mut f, true)?; + Ok(*wav_file.properties()) } #[test] @@ -21,10 +22,31 @@ fn hound() { if path.is_file() && path.extension().unwrap() == "wav" { println!("Name: {}", path.display()); let wav_reader = WavReader::open(&path).unwrap(); - let lofty = get_properties(&path); - assert_eq!(wav_reader.spec().channels, lofty.channels() as u16); - assert_eq!(wav_reader.spec().sample_rate, lofty.sample_rate()); - assert_eq!(wav_reader.spec().bits_per_sample, lofty.bit_depth() as u16); + let lofty = get_properties(&path).unwrap(); + assert_eq!(lofty.channels() as u16, wav_reader.spec().channels); + assert_eq!(lofty.sample_rate(), wav_reader.spec().sample_rate); + assert_eq!(lofty.bit_depth() as u16, wav_reader.spec().bits_per_sample); + } + } +} + +#[test] +fn hound_fuzz() { + let paths = fs::read_dir("tests/files/assets/hound/fuzz").unwrap(); + + for path in paths { + let path = path.unwrap().path(); + if path.is_file() && path.extension().unwrap() == "wav" { + println!("Name: {}", path.display()); + if let Ok(wav_reader) = WavReader::open(&path) { + let lofty = get_properties(&path).unwrap(); + println!("{lofty:#?}"); + assert_eq!(lofty.channels() as u16, wav_reader.spec().channels); + assert_eq!(lofty.sample_rate(), wav_reader.spec().sample_rate); + assert_eq!(lofty.bit_depth() as u16, wav_reader.spec().bits_per_sample); + } else if get_properties(&path).is_ok() { + println!("We are even better for this file!"); + } } } }