From be87d27d6bde0f39cedcdb9d990e3aec66452a1b Mon Sep 17 00:00:00 2001 From: jakka Date: Thu, 24 Jul 2025 21:34:21 +0300 Subject: started testing new symphonia commits --- Cargo.lock | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 2 +- src/flac.rs | 101 +++++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 177 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ed4816..ed7bae4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,6 +58,12 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + [[package]] name = "bitflags" version = "2.9.1" @@ -70,6 +76,12 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" + [[package]] name = "byteorder" version = "1.5.0" @@ -133,11 +145,6 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" -[[package]] -name = "claxon" -version = "0.4.3" -source = "git+https://github.com/justjakka/claxon.git#919a0fe9902f2b4f2bd1152772cca746eb0df7d2" - [[package]] name = "cmake" version = "0.1.54" @@ -231,7 +238,6 @@ dependencies = [ "anyhow", "clap", "clap_complete", - "claxon", "console", "ctrlc", "directories", @@ -239,6 +245,7 @@ dependencies = [ "indicatif", "metaflac", "rusqlite", + "symphonia", "walkdir", ] @@ -313,6 +320,12 @@ dependencies = [ "wasm-bindgen", ] +[[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.174" @@ -378,6 +391,24 @@ dependencies = [ "libc", ] +[[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" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -437,6 +468,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + [[package]] name = "rusqlite" version = "0.36.0" @@ -478,6 +515,62 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "symphonia" +version = "0.5.4" +source = "git+https://github.com/pdeljanov/Symphonia.git?branch=dev-0.6#ecefdd0b796207eae7d18e8c26ce59c46c5cb5f6" +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#ecefdd0b796207eae7d18e8c26ce59c46c5cb5f6" +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#ecefdd0b796207eae7d18e8c26ce59c46c5cb5f6" +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#ecefdd0b796207eae7d18e8c26ce59c46c5cb5f6" +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#ecefdd0b796207eae7d18e8c26ce59c46c5cb5f6" +dependencies = [ + "lazy_static", + "log", + "regex-lite", + "smallvec", + "symphonia-core", +] + [[package]] name = "syn" version = "2.0.104" diff --git a/Cargo.toml b/Cargo.toml index d759241..bef2c9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,12 +18,12 @@ flac-bound = { version = "0.5.0", default-features = false } indicatif = { version = "0.18.0", features = ["improved_unicode"] } walkdir = "2.5.0" console = { version = "0.16.0", features = ["windows-console-colors"] } -claxon = { git = "https://github.com/justjakka/claxon.git" } metaflac = "0.2.8" rusqlite = { version = "0.36.0", default-features = false, features = [ "modern_sqlite", ] } ctrlc = "3.4.7" +symphonia = { git = "https://github.com/pdeljanov/Symphonia.git", branch = "dev-0.6", version = "0.5.4", default-features = false, features = ["flac"] } [features] default = ["bundled"] diff --git a/src/flac.rs b/src/flac.rs index 7b542ac..f82c29f 100644 --- a/src/flac.rs +++ b/src/flac.rs @@ -1,14 +1,30 @@ use anyhow::{Result, anyhow}; -use claxon::{FlacReader, FlacReaderOptions}; use flac_bound::FlacEncoder; use metaflac::{Block, Tag}; use std::{ - path::Path, + fs::File, + path::{Path, PathBuf}, sync::{ Arc, atomic::{AtomicBool, Ordering}, }, }; +use symphonia::core::{ + audio::{ + Audio, AudioBuffer, AudioBytes, + sample::{Sample, SampleFormat}, + }, + codecs::audio::{AudioDecoder, AudioDecoderOptions}, + formats::{FormatOptions, FormatReader, TrackType, probe::Hint}, + io::MediaSourceStream, + meta::MetadataOptions, +}; + +struct StreamInfo { + channels: u32, + bps: u32, + sample_rate: u32, +} pub const CURRENT_VENDOR: &str = "reference libFLAC 1.5.0 20250211"; @@ -37,20 +53,54 @@ fn write_tags(filename: impl AsRef) -> Result<()> { Ok(()) } +fn init_decoder( + file: Box, +) -> Result<( + u32, + Box, + StreamInfo, + Box, +)> { + let mut hint = Hint::new(); + hint.with_extension("flac"); + let mss = MediaSourceStream::new(file, Default::default()); + let fmt_opts = FormatOptions::default(); + let meta_opts: MetadataOptions = Default::default(); + let dec_opts: AudioDecoderOptions = Default::default(); + + let probed = symphonia::default::get_probe().probe(&hint, mss, fmt_opts, meta_opts)?; + + let track = probed.default_track(TrackType::Audio).unwrap(); + + let codec_params = track.codec_params.as_ref().unwrap().audio().unwrap(); + + let decoder = symphonia::default::get_codecs().make_audio_decoder(&codec_params, &dec_opts)?; + + let track_id = track.id; + + let streaminfo = StreamInfo { + channels: u32::try_from(codec_params.channels.clone().unwrap().count())?, + bps: codec_params.bits_per_sample.unwrap(), + sample_rate: codec_params.sample_rate.unwrap(), + }; + + Ok((track_id, decoder, streaminfo, probed)) +} + fn encode_file(filename: impl AsRef, handler: Arc) -> Result { let temp_name = filename.as_ref().with_extension("tmp"); if temp_name.exists() { std::fs::remove_file(&temp_name)?; } - let mut decoder = FlacReader::open(&filename)?; - let streaminfo = decoder.streaminfo(); - let num_channels: usize = streaminfo.channels.try_into()?; + let file = Box::new(File::open(&filename)?); + + let (id, mut decoder, streaminfo, mut probe) = init_decoder(file)?; let mut encoder = if let Some(encoder) = FlacEncoder::new() { if let Ok(encoder) = encoder .channels(streaminfo.channels) - .bits_per_sample(streaminfo.bits_per_sample) + .bits_per_sample(streaminfo.bps) .sample_rate(streaminfo.sample_rate) .compression_level(8) .verify(false) @@ -64,29 +114,32 @@ fn encode_file(filename: impl AsRef, handler: Arc) -> Result> = None; while handler.load(Ordering::SeqCst) { - match frame_reader.read_next_or_eof(block_buffer) { - Ok(Some(block)) => { - for ch in 0..block.channels() { - buffer.push(block.channel(ch)); + let packet = if let Some(packet) = probe.next_packet()? { + packet + } else { + break; + }; + + if packet.track_id() != id { + continue; + } + + match decoder.decode(&packet) { + Ok(audio_buf) => { + if sample_buf.is_none() { + let spec = *audio_buf.spec(); + + sample_buf = Some(AudioBuffer::new(spec, audio_buf.capacity())); } - if encoder.process(&buffer).is_err() { - return Err(anyhow!( - "Error while processing samples:\t{:?}", - encoder.state() - )); - }; - buffer.clear(); - buffer = buffer.into_iter().map(|_| unreachable!()).collect(); - block_buffer = block.into_buffer(); + if let Some(buf) = &mut sample_buf { + todo!() + } } - Ok(None) => break, - Err(error) => return Err(error.into()), + Err(err) => return Err(err.into()), } } -- cgit v1.3.1