summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhspetersson <jhspetersson@gmail.com>2024-01-10 17:37:28 +0100
committerjhspetersson <jhspetersson@gmail.com>2024-01-10 17:37:28 +0100
commitba2e3ada20ba2dd5a16d3dd115dafa1bb159a2fd (patch)
tree68a42da0721edc5dfe47b924db9a215d05c2866b
parent6fb0fb592fc9bff464b830a45a2cdea7561c9c26 (diff)
support duration extraction from WAV files
-rw-r--r--Cargo.lock25
-rw-r--r--Cargo.toml1
-rw-r--r--resources/test/audio/silent.wavbin0 -> 1440078 bytes
-rw-r--r--src/util/duration/mod.rs5
-rw-r--r--src/util/duration/wav.rs47
5 files changed, 77 insertions, 1 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c4767b8..947be69 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index 222a5b8..574ff10 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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
new file mode 100644
index 0000000..46af45e
--- /dev/null
+++ b/resources/test/audio/silent.wav
Binary files differ
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(())
+ }
+}