summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakka <jakkadoujin@gmail.com>2025-06-05 15:54:08 +0300
committerjakka <jakkadoujin@gmail.com>2025-06-05 15:54:08 +0300
commit4ecfc50de96a07de00757a625546b9fc43e9c2c3 (patch)
tree0c536be78e6661e083e71ae2673bd50d1882d0b8
parent5b3c64bc68a22d9b6a1cc8fe7082f589ed8b6983 (diff)
switched to symphonia 0.6-dev for flac decoding, no 32 bit flac implementation
-rw-r--r--Cargo.lock103
-rw-r--r--Cargo.toml3
-rw-r--r--src/flac.rs172
-rw-r--r--src/main.rs6
4 files changed, 193 insertions, 91 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2b908d9..e99fb02 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -15,6 +15,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
+name = "bitflags"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+
+[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -51,12 +57,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
-name = "claxon"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688"
-
-[[package]]
name = "cmake"
version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -121,6 +121,12 @@ dependencies = [
]
[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
name = "libc"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -137,6 +143,12 @@ dependencies = [
]
[[package]]
+name = "log"
+version = "0.4.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+
+[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -157,6 +169,15 @@ dependencies = [
]
[[package]]
+name = "num-complex"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -170,20 +191,88 @@ name = "reencoder"
version = "0.1.0"
dependencies = [
"anyhow",
- "claxon",
"flac-bound",
"i24",
"md-5",
"metaflac",
+ "symphonia",
]
[[package]]
+name = "regex-lite"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
+
+[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
+name = "smallvec"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
+
+[[package]]
+name = "symphonia"
+version = "0.5.4"
+source = "git+https://github.com/pdeljanov/Symphonia.git?branch=dev-0.6#c7efbcb05dde274d13a50b4f7aac9db4c773f602"
+dependencies = [
+ "lazy_static",
+ "symphonia-bundle-flac",
+ "symphonia-core",
+ "symphonia-metadata",
+]
+
+[[package]]
+name = "symphonia-bundle-flac"
+version = "0.5.4"
+source = "git+https://github.com/pdeljanov/Symphonia.git?branch=dev-0.6#c7efbcb05dde274d13a50b4f7aac9db4c773f602"
+dependencies = [
+ "log",
+ "symphonia-common",
+ "symphonia-core",
+ "symphonia-metadata",
+]
+
+[[package]]
+name = "symphonia-common"
+version = "0.5.4"
+source = "git+https://github.com/pdeljanov/Symphonia.git?branch=dev-0.6#c7efbcb05dde274d13a50b4f7aac9db4c773f602"
+dependencies = [
+ "symphonia-core",
+ "symphonia-metadata",
+]
+
+[[package]]
+name = "symphonia-core"
+version = "0.5.4"
+source = "git+https://github.com/pdeljanov/Symphonia.git?branch=dev-0.6#c7efbcb05dde274d13a50b4f7aac9db4c773f602"
+dependencies = [
+ "bitflags",
+ "bytemuck",
+ "lazy_static",
+ "log",
+ "num-complex",
+ "smallvec",
+]
+
+[[package]]
+name = "symphonia-metadata"
+version = "0.5.4"
+source = "git+https://github.com/pdeljanov/Symphonia.git?branch=dev-0.6#c7efbcb05dde274d13a50b4f7aac9db4c773f602"
+dependencies = [
+ "lazy_static",
+ "log",
+ "regex-lite",
+ "smallvec",
+ "symphonia-core",
+]
+
+[[package]]
name = "typenum"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 06f9cba..525b072 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,11 +2,12 @@
name = "reencoder"
version = "0.1.0"
edition = "2024"
+repository = "https://github.com/justjakka/reencoder/"
[dependencies]
anyhow = "1.0.98"
-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"
+symphonia = { git = "https://github.com/pdeljanov/Symphonia.git", branch = "dev-0.6", default-features = false, features = ["flac"] }
diff --git a/src/flac.rs b/src/flac.rs
index 7da93cb..af95a7a 100644
--- a/src/flac.rs
+++ b/src/flac.rs
@@ -1,16 +1,20 @@
use anyhow::{Result, anyhow};
-use claxon::FlacReader;
use flac_bound::{FlacEncoder, WriteWrapper};
use i24::i24;
use md5::{Digest, Md5};
use metaflac::{Block, Tag};
use std::fs::File;
+use symphonia::core::{
+ audio::{Audio, GenericAudioBufferRef},
+ formats::{FormatOptions, TrackType, probe::Hint},
+ io::MediaSourceStream,
+ meta::MetadataOptions,
+};
struct StreamConfig {
channels: u32,
bits_per_sample: Bps,
sample_rate: u32,
- total_samples_estimate: u64,
}
enum Bps {
@@ -38,85 +42,39 @@ impl Bps {
}
}
-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 * usize::try_from(config.channels).unwrap())
- {
- enc.process_interleaved(samples, u32::try_from(samples.len()).unwrap() / config.channels)
- .unwrap();
- let _ = samples
- .iter()
- .map(|sample| hasher.update((i16::try_from(*sample)).unwrap().to_le_bytes()))
- .collect::<Vec<_>>();
- }
- Ok(())
-}
+pub fn encode_file(file: &std::path::Path) -> Result<()> {
+ let src = std::fs::File::open(file)?;
+ let mss = MediaSourceStream::new(Box::new(src), Default::default());
+ let mut hint = Hint::new();
+ hint.with_extension("flac");
-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 * usize::try_from(config.channels).unwrap())
- {
- enc.process_interleaved(samples, u32::try_from(samples.len()).unwrap() / config.channels)
- .unwrap();
- let _ = samples
- .iter()
- .map(|sample| hasher.update((i24::try_from(*sample)).unwrap().to_le_bytes()))
- .collect::<Vec<_>>();
- }
- Ok(())
-}
+ let format_opts: FormatOptions = Default::default();
+ let metadata_opts: MetadataOptions = Default::default();
-/* 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 * usize::try_from(config.channels).unwrap())
- {
- enc.process_interleaved(samples, u32::try_from(samples.len()).unwrap() / config.channels)
- .unwrap();
- let _ = samples
- .iter()
- .map(|sample| hasher.update(sample.to_le_bytes()))
- .collect::<Vec<_>>();
- }
- for sample in reader.samples() {
- sample?;
- }
- Ok(())
-} */
+ let mut format = symphonia::default::get_probe()
+ .probe(&hint, mss, format_opts, metadata_opts)
+ .unwrap();
+
+ let track = format.default_track(TrackType::Audio).unwrap();
+
+ let mut decoder = symphonia::default::get_codecs()
+ .make_audio_decoder(
+ track.codec_params.as_ref().unwrap().audio().unwrap(),
+ &Default::default(),
+ )
+ .unwrap();
+
+ let track_id = track.id;
+
+ let params = track.codec_params.as_ref().unwrap().audio().unwrap();
-pub fn encode_file(file: &std::path::Path) -> Result<()> {
- let reader = claxon::FlacReader::open(file)?;
let config = StreamConfig {
- channels: reader.streaminfo().channels,
- bits_per_sample: Bps::new(reader.streaminfo().bits_per_sample)?,
- sample_rate: reader.streaminfo().sample_rate,
- total_samples_estimate: reader.streaminfo().samples.unwrap(),
+ channels: u32::try_from(params.channels.as_ref().unwrap().count()).unwrap(),
+ bits_per_sample: Bps::new(params.bits_per_sample.unwrap())?,
+ sample_rate: params.sample_rate.unwrap(),
};
- let tempname = format!("{}.{}", file.display(), "tmp");
+ let tempname = format!("{}.tmp", file.display());
let mut outf = File::create(&tempname)?;
let mut outw = WriteWrapper(&mut outf);
@@ -125,7 +83,6 @@ pub fn encode_file(file: &std::path::Path) -> Result<()> {
.channels(config.channels)
.bits_per_sample(config.bits_per_sample.value())
.sample_rate(config.sample_rate)
- .total_samples_estimate(config.total_samples_estimate)
.compression_level(8)
.verify(false)
.init_write(&mut outw)
@@ -133,12 +90,63 @@ pub fn encode_file(file: &std::path::Path) -> Result<()> {
let mut hasher = Md5::new();
- 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)?, */
- Bps::_32 => unimplemented!("32bit flac isnt supported by claxon")
- };
+ let mut sample_buf: Vec<i32> = Vec::new();
+
+ loop {
+ let packet = match format.next_packet() {
+ Ok(Some(packet)) => packet,
+ Ok(None) => break,
+ Err(error) => return Err(error.into()),
+ };
+
+ if packet.track_id() != track_id {
+ continue;
+ }
+
+ match decoder.decode(&packet) {
+ Ok(audio_buf) => match audio_buf {
+ GenericAudioBufferRef::S32(buf) => {
+ match config.bits_per_sample {
+ Bps::_16 => {
+ let _ = buf
+ .iter_interleaved()
+ .map(|sample| {
+ let real_sample =
+ sample >> (32 - config.bits_per_sample.value());
+ hasher
+ .update(i16::try_from(real_sample).unwrap().to_le_bytes());
+ sample_buf.push(real_sample);
+ })
+ .collect::<Vec<_>>();
+ }
+ Bps::_24 => {
+ let _ = buf
+ .iter_interleaved()
+ .map(|sample| {
+ let real_sample =
+ sample >> (32 - config.bits_per_sample.value());
+ hasher.update(
+ i24::try_from_i32(real_sample).unwrap().to_le_bytes(),
+ );
+ sample_buf.push(real_sample);
+ })
+ .collect::<Vec<_>>();
+ }
+ Bps::_32 => return Err(anyhow!("how did you get here")),
+ }
+
+ enc.process_interleaved(
+ sample_buf.as_slice(),
+ u32::try_from(buf.samples_planar()).unwrap(),
+ )
+ .unwrap();
+ sample_buf.clear();
+ }
+ _ => return Err(anyhow!("unsupported codec")),
+ },
+ Err(err) => return Err(err.into()),
+ }
+ }
if let Err(enc) = enc.finish() {
return Err(anyhow!("Encoding failed:\t{:?}", enc.state()));
diff --git a/src/main.rs b/src/main.rs
index 4c3ba1b..5e4657e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,11 @@
mod flac;
fn main() {
- todo!()
+ let start = std::time::Instant::now();
+ if let Err(err) = flac::encode_file(std::path::Path::new("16bit.flac")) {
+ println!("{}", err)
+ };
+ println!("{}", start.elapsed().as_secs())
}
#[cfg(test)]