summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock104
-rw-r--r--Cargo.toml2
-rw-r--r--src/flac.rs134
-rw-r--r--src/main.rs64
4 files changed, 200 insertions, 104 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bec0084..786a917 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -24,6 +24,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
name = "backtrace"
version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -39,16 +45,6 @@ dependencies = [
]
[[package]]
-name = "bincode"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
-dependencies = [
- "serde",
- "unty",
-]
-
-[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -58,6 +54,12 @@ dependencies = [
]
[[package]]
+name = "bytemuck"
+version = "1.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
+
+[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -145,6 +147,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
+name = "i24"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe4e9f59fce450959a3bfe4a762ebba4afe2327ab3795ba11c489233c5d29733"
+dependencies = [
+ "bytemuck",
+ "num-traits",
+]
+
+[[package]]
name = "libc"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -196,6 +208,15 @@ dependencies = [
]
[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
name = "object"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -211,31 +232,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
-name = "proc-macro2"
-version = "1.0.95"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
name = "reencoder"
version = "0.1.0"
dependencies = [
"anyhow",
- "bincode",
"claxon",
"flac-bound",
+ "i24",
"md-5",
"metaflac",
"tokio",
@@ -248,43 +251,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
-name = "serde"
-version = "1.0.219"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.219"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
-name = "syn"
-version = "2.0.101"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
name = "tokio"
version = "1.45.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -301,18 +273,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
-name = "unicode-ident"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
-
-[[package]]
-name = "unty"
-version = "0.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
-
-[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 72bc5fc..380c178 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,9 +5,9 @@ edition = "2024"
[dependencies]
anyhow = "1.0.98"
-bincode = { version = "2.0.1", default-features = false, features = ["std"] }
claxon = "0.4.3"
flac-bound = { version = "0.5.0", features = ["libflac-noogg"], default-features = false }
+i24 = "2.1.0"
md-5 = "0.10.6"
metaflac = "0.2.8"
tokio = "1.45.1"
diff --git a/src/flac.rs b/src/flac.rs
index 92c4b77..8653881 100644
--- a/src/flac.rs
+++ b/src/flac.rs
@@ -1,32 +1,126 @@
use anyhow::{Result, anyhow};
+use claxon::FlacReader;
use flac_bound::{FlacEncoder, WriteWrapper};
+use i24::i24;
use md5::{Digest, Md5};
use metaflac::Tag;
use std::fs::File;
-#[derive(Debug)]
struct StreamConfig {
channels: u32,
- bits_per_sample: u32,
+ bits_per_sample: Bps,
sample_rate: u32,
total_samples_estimate: u64,
}
+enum Bps {
+ _16,
+ _24,
+ _32,
+}
+
+impl Bps {
+ fn new(num: u32) -> Result<Self> {
+ match num {
+ 16 => Ok(Bps::_16),
+ 24 => Ok(Bps::_24),
+ 32 => Ok(Bps::_32),
+ _ => Err(anyhow!("Invalid BPS")),
+ }
+ }
+
+ fn value(&self) -> u32 {
+ match self {
+ Bps::_16 => 16,
+ Bps::_24 => 24,
+ Bps::_32 => 32,
+ }
+ }
+}
+
+fn process_samples_i16(
+ hasher: &mut impl Digest,
+ mut reader: FlacReader<File>,
+ enc: &mut FlacEncoder,
+ config: &StreamConfig,
+) -> Result<()> {
+ for samples in reader
+ .samples()
+ .map(|sample| sample.unwrap())
+ .collect::<Vec<_>>()
+ .chunks(4096)
+ {
+ enc.process_interleaved(samples, 4096 / config.channels)
+ .unwrap();
+ let _ = samples
+ .iter()
+ .map(|sample| hasher.update((i16::try_from(*sample)).unwrap().to_le_bytes()))
+ .collect::<Vec<_>>();
+ }
+ Ok(())
+}
+
+fn process_samples_i24(
+ hasher: &mut impl Digest,
+ mut reader: FlacReader<File>,
+ enc: &mut FlacEncoder,
+ config: &StreamConfig,
+) -> Result<()> {
+ for samples in reader
+ .samples()
+ .map(|sample| sample.unwrap())
+ .collect::<Vec<_>>()
+ .chunks(4096)
+ {
+ enc.process_interleaved(samples, 4096 / config.channels)
+ .unwrap();
+ let _ = samples
+ .iter()
+ .map(|sample| hasher.update((i24::try_from(*sample)).unwrap().to_le_bytes()))
+ .collect::<Vec<_>>();
+ }
+ Ok(())
+}
+
+fn process_samples_i32(
+ hasher: &mut impl Digest,
+ mut reader: FlacReader<File>,
+ enc: &mut FlacEncoder,
+ config: &StreamConfig,
+) -> Result<()> {
+ for samples in reader
+ .samples()
+ .map(|sample| sample.unwrap())
+ .collect::<Vec<_>>()
+ .chunks(4096)
+ {
+ enc.process_interleaved(samples, 4096 / config.channels)
+ .unwrap();
+ let _ = samples
+ .iter()
+ .map(|sample| hasher.update(sample.to_le_bytes()))
+ .collect::<Vec<_>>();
+ }
+ Ok(())
+}
+
pub fn encode_file(file: &std::path::Path) -> Result<()> {
- let mut reader = claxon::FlacReader::open(file)?;
+ let reader = claxon::FlacReader::open(file)?;
let config = StreamConfig {
channels: reader.streaminfo().channels,
- bits_per_sample: reader.streaminfo().bits_per_sample,
+ bits_per_sample: Bps::new(reader.streaminfo().bits_per_sample)?,
sample_rate: reader.streaminfo().sample_rate,
total_samples_estimate: reader.streaminfo().samples.unwrap(),
};
+
let tempname = format!("{}.{}", file.display(), "tmp");
+
let mut outf = File::create(&tempname)?;
let mut outw = WriteWrapper(&mut outf);
let mut enc = FlacEncoder::new()
.unwrap()
.channels(config.channels)
- .bits_per_sample(config.bits_per_sample)
+ .bits_per_sample(config.bits_per_sample.value())
.sample_rate(config.sample_rate)
.total_samples_estimate(config.total_samples_estimate)
.compression_level(8)
@@ -35,30 +129,15 @@ pub fn encode_file(file: &std::path::Path) -> Result<()> {
.unwrap();
let mut hasher = Md5::new();
- let mut bytes = Vec::new();
- for samples in reader
- .samples()
- .map(|sample| sample.unwrap())
- .collect::<Vec<_>>()
- .chunks(4096)
- {
- enc.process_interleaved(samples, 4096 / config.channels).unwrap();
- let _ = samples
- .iter()
- .map(|sample| {
- for byte in sample.to_le_bytes() {
- bytes.push(byte)
- }
- })
- .collect::<Vec<_>>();
- hasher.update(&bytes);
- bytes.clear();
- }
+ match config.bits_per_sample {
+ Bps::_16 => process_samples_i16(&mut hasher, reader, &mut enc, &config)?,
+ Bps::_24 => process_samples_i24(&mut hasher, reader, &mut enc, &config)?,
+ Bps::_32 => process_samples_i32(&mut hasher, reader, &mut enc, &config)?,
+ };
- match enc.finish() {
- Ok(_) => {}
- Err(enc) => return Err(anyhow!("Encoding failed:\t{:?}", enc.state())),
+ if let Err(enc) = enc.finish() {
+ return Err(anyhow!("Encoding failed:\t{:?}", enc.state()));
}
/* let source_tags = Tag::read_from_path(file)?;
@@ -68,7 +147,6 @@ pub fn encode_file(file: &std::path::Path) -> Result<()> {
for block in source_tags.blocks() {
todo!()
} */
-
let mut tags = Tag::read_from_path(tempname)?;
let mut streaminfo = tags.get_streaminfo().unwrap().clone();
streaminfo.md5 = hasher.finalize()[..].to_vec();
diff --git a/src/main.rs b/src/main.rs
index ba95650..89343f1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,65 @@
mod flac;
fn main() {
- if let Err(error) = flac::encode_file(std::path::Path::new("./1.flac")) {
- println!("{}", error)
- };
+ todo!()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use metaflac::Tag;
+ #[test]
+ fn bit16() {
+ flac::encode_file(std::path::Path::new("16bit.flac")).unwrap();
+ let target_md5 = Tag::read_from_path("16bit.flac.tmp")
+ .unwrap()
+ .get_streaminfo()
+ .unwrap()
+ .md5
+ .clone();
+ let source_md5 = Tag::read_from_path("16bit.flac")
+ .unwrap()
+ .get_streaminfo()
+ .unwrap()
+ .md5
+ .clone();
+ std::fs::remove_file(std::path::Path::new("16bit.flac.tmp")).unwrap();
+ assert_eq!(target_md5, source_md5);
+ }
+ #[test]
+ fn bit24() {
+ flac::encode_file(std::path::Path::new("24bit.flac")).unwrap();
+ let target_md5 = Tag::read_from_path("24bit.flac.tmp")
+ .unwrap()
+ .get_streaminfo()
+ .unwrap()
+ .md5
+ .clone();
+ let source_md5 = Tag::read_from_path("24bit.flac")
+ .unwrap()
+ .get_streaminfo()
+ .unwrap()
+ .md5
+ .clone();
+ std::fs::remove_file(std::path::Path::new("24bit.flac.tmp")).unwrap();
+ assert_eq!(target_md5, source_md5);
+ }
+ #[test]
+ fn bit32() {
+ flac::encode_file(std::path::Path::new("32bit.flac")).unwrap();
+ let target_md5 = Tag::read_from_path("32bit.flac.tmp")
+ .unwrap()
+ .get_streaminfo()
+ .unwrap()
+ .md5
+ .clone();
+ let source_md5 = Tag::read_from_path("32bit.flac")
+ .unwrap()
+ .get_streaminfo()
+ .unwrap()
+ .md5
+ .clone();
+ std::fs::remove_file(std::path::Path::new("32bit.flac.tmp")).unwrap();
+ assert_eq!(target_md5, source_md5);
+ }
}