diff options
author | jhspetersson <jhspetersson@gmail.com> | 2024-01-10 17:37:28 +0100 |
---|---|---|
committer | jhspetersson <jhspetersson@gmail.com> | 2024-01-10 17:37:28 +0100 |
commit | ba2e3ada20ba2dd5a16d3dd115dafa1bb159a2fd (patch) | |
tree | 68a42da0721edc5dfe47b924db9a215d05c2866b | |
parent | 6fb0fb592fc9bff464b830a45a2cdea7561c9c26 (diff) |
support duration extraction from WAV files
-rw-r--r-- | Cargo.lock | 25 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | resources/test/audio/silent.wav | bin | 0 -> 1440078 bytes | |||
-rw-r--r-- | src/util/duration/mod.rs | 5 | ||||
-rw-r--r-- | src/util/duration/wav.rs | 47 |
5 files changed, 77 insertions, 1 deletions
@@ -146,6 +146,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" + +[[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -509,6 +515,7 @@ dependencies = [ "update-informer", "uzers", "wana_kana", + "wavers", "xattr", "zip", ] @@ -1095,6 +1102,12 @@ dependencies = [ ] [[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] name = "pbkdf2" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2060,6 +2073,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] +name = "wavers" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93a97475d1432afab6f3e845a7934f6de1bd39d495aedc93dafb54e62f57be2c" +dependencies = [ + "bytemuck", + "num-traits", + "paste", + "thiserror", +] + +[[package]] name = "web-sys" version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -47,6 +47,7 @@ toml = "0.8" tree_magic_mini = { version = "3.0", features = [ "tree_magic_db" ] } update-informer = { version = "1.1.0", optional = true } wana_kana = "3.0" +wavers = "1.1" zip = "0.6" [target.'cfg(unix)'.dependencies] diff --git a/resources/test/audio/silent.wav b/resources/test/audio/silent.wav Binary files differnew file mode 100644 index 0000000..46af45e --- /dev/null +++ b/resources/test/audio/silent.wav diff --git a/src/util/duration/mod.rs b/src/util/duration/mod.rs index 8353e49..4d98274 100644 --- a/src/util/duration/mod.rs +++ b/src/util/duration/mod.rs @@ -3,6 +3,7 @@ use std::io; mod mkv; mod mp3; mod mp4; +mod wav; use std::path::Path; @@ -11,6 +12,7 @@ use mp3_metadata::MP3Metadata; use mkv::MkvDurationExtractor; use mp3::Mp3DurationExtractor; use mp4::Mp4DurationExtractor; +use wav::WavDurationExtractor; #[derive(PartialEq, Eq, Clone, Debug)] pub struct Duration { @@ -22,10 +24,11 @@ pub trait DurationExtractor { fn try_read_duration(&self, path: &Path, mp3_metadata: &Option<MP3Metadata>) -> io::Result<Option<Duration>>; } -const EXTRACTORS: [&dyn DurationExtractor; 3] = [ +const EXTRACTORS: [&dyn DurationExtractor; 4] = [ &Mp3DurationExtractor, &Mp4DurationExtractor, &MkvDurationExtractor, + &WavDurationExtractor, ]; pub fn get_duration<T: AsRef<Path>>(path: T, mp3_metadata: &Option<MP3Metadata>) -> Option<Duration> { diff --git a/src/util/duration/wav.rs b/src/util/duration/wav.rs new file mode 100644 index 0000000..037994f --- /dev/null +++ b/src/util/duration/wav.rs @@ -0,0 +1,47 @@ +use std::io; +use std::path::Path; + +use mp3_metadata::MP3Metadata; + +use wavers::Wav; + +use crate::util::duration::DurationExtractor; +use crate::util::Duration; + +pub struct WavDurationExtractor; + +impl DurationExtractor for WavDurationExtractor { + fn supports_ext(&self, ext_lowercase: &str) -> bool { + "wav" == ext_lowercase + } + + fn try_read_duration( + &self, + path: &Path, + _: &Option<MP3Metadata>, + ) -> io::Result<Option<Duration>> { + let wav: Wav<i16> = Wav::from_path(path).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + Ok(Some(Duration { length: wav.duration() as usize })) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::util::duration::DurationExtractor; + use crate::util::Duration; + use std::error::Error; + use std::path::PathBuf; + + #[test] + fn test_success() -> Result<(), Box<dyn Error>> { + let path_string = + std::env::var("CARGO_MANIFEST_DIR")? + "/resources/test/" + "audio/silent.wav"; + let path = PathBuf::from(path_string); + assert_eq!( + WavDurationExtractor.try_read_duration(&path, &None)?, + Some(Duration { length: 15 }), + ); + Ok(()) + } +} |