diff options
| author | jakka <jakkadoujin@gmail.com> | 2025-06-04 20:01:07 +0300 |
|---|---|---|
| committer | jakka <jakkadoujin@gmail.com> | 2025-06-04 20:01:07 +0300 |
| commit | 3b55294f1fc09a957ca63c3a9a718b1082b9a894 (patch) | |
| tree | e9923ca12127130cc69953a8b03e6d7f04236e9e /src/flac.rs | |
| parent | 5a39e523da7f4fe2c9c1e6c369a366162be122fa (diff) | |
implemented flac reencoding. started working on md5sum implementation
Diffstat (limited to 'src/flac.rs')
| -rw-r--r-- | src/flac.rs | 149 |
1 files changed, 49 insertions, 100 deletions
diff --git a/src/flac.rs b/src/flac.rs index 8b03664..1881756 100644 --- a/src/flac.rs +++ b/src/flac.rs @@ -1,130 +1,79 @@ use anyhow::{Result, anyhow}; use flac_bound::{FlacEncoder, WriteWrapper}; +use md5::{Digest, Md5}; +use metaflac::Tag; use std::fs::File; -use symphonia::core::{ - audio::SampleBuffer, - codecs::{DecoderOptions, CODEC_TYPE_NULL}, - errors::Error::DecodeError, - formats::{FormatOptions, Track}, - io::MediaSourceStream, - meta::MetadataOptions, - probe::{Hint, ProbeResult}, -}; #[derive(Debug)] struct StreamConfig { channels: u32, - bits_per_sample: Bps, + bits_per_sample: u32, sample_rate: u32, total_samples_estimate: u64, } -#[derive(Debug)] -enum Bps { - _16, - _24, - _32 -} - -fn get_probe(file: &std::path::Path) -> Result<ProbeResult> { - 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"); - let meta_opts: MetadataOptions = Default::default(); - let fmt_opts: FormatOptions = Default::default(); - Ok(symphonia::default::get_probe().format(&hint, mss, &fmt_opts, &meta_opts)?) -} - -fn read_streaminfo(track: &Track) -> Result<StreamConfig> { - let params = &track.codec_params; - - Ok(StreamConfig { - channels: params.channels.unwrap().count() as u32, - bits_per_sample: match params.bits_per_sample.unwrap() { - 16 => Bps::_16, - 24 => Bps::_24, - 32 => Bps::_32, - _ => return Err(anyhow!("invalid Bps")) - }, - sample_rate: params.sample_rate.unwrap(), - total_samples_estimate: params.n_frames.unwrap(), - }) -} - pub fn encode_file(file: &std::path::Path) -> Result<()> { - let probed = get_probe(file)?; - let mut format = probed.format; - let dec_opts: DecoderOptions = Default::default(); - let track = format - .tracks() - .iter() - .find(|t| t.codec_params.codec != CODEC_TYPE_NULL) - .unwrap(); - - let config = read_streaminfo(track)?; - - let mut outf = File::create(format!("{}.{}", file.display(), "tmp"))?; + let mut reader = claxon::FlacReader::open(file)?; + let config = StreamConfig { + channels: reader.streaminfo().channels, + bits_per_sample: 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(match config.bits_per_sample { - Bps::_16 => 16, - Bps::_24 => 24, - Bps::_32 => 32 - }) + .bits_per_sample(config.bits_per_sample) .sample_rate(config.sample_rate) .total_samples_estimate(config.total_samples_estimate) .compression_level(8) - .verify(true) + .verify(false) .init_write(&mut outw) .unwrap(); - let mut decoder = symphonia::default::get_codecs() - .make(&track.codec_params, &dec_opts) - .unwrap(); - let track_id = track.id; - - let mut sample_buf = None; + let mut hasher = Md5::new(); + let mut bytes = Vec::new(); - loop { - let packet = format.next_packet().unwrap(); + for samples in reader + .samples() + .map(|sample| sample.unwrap()) + .collect::<Vec<_>>() + .chunks(4096) + { + enc.process_interleaved(samples, 2048).unwrap(); + let _ = samples + .iter() + .map(|sample| { + for byte in sample.to_le_bytes() { + bytes.push(byte) + } + }) + .collect::<Vec<_>>(); + hasher.update(&bytes); + bytes.clear(); + } - if packet.track_id() != track_id { - continue; - } + match enc.finish() { + Ok(_) => {} + Err(enc) => return Err(anyhow!("Encoding failed:\t{:?}", enc.state())), + } - match decoder.decode(&packet) { - Ok(audio_buf) => { - if sample_buf.is_none() { - let spec = *audio_buf.spec(); + /* let source_tags = Tag::read_from_path(file)?; + let mut target_tags = Tag::read_from_path(tempname)?; - let duration = audio_buf.capacity() as u64; - sample_buf = Some(SampleBuffer::<i16>::new(duration, spec)); - /* match config.bits_per_sample { - Bps::_16 => sample_buf = Some(SampleBuffer::<i16>::new(duration, spec)), - Bps::_24 => sample_buf = Some(SampleBuffer::<i24>::new(duration, spec)), - Bps::_32 => sample_buf = Some(SampleBuffer::<i32>::new(duration, spec)), - } */ - } + for block in source_tags.blocks() { + todo!() + } */ - if let Some(buf) = &mut sample_buf { - buf.copy_interleaved_ref(audio_buf); - let mut samples = Vec::new(); - _ = buf.samples().iter().map(|sample| samples.push(*sample as i32)).collect::<Vec<_>>(); - enc.process_interleaved(samples.as_slice(), samples.iter().len() as u32 / config.channels) - .unwrap(); - } - } - Err(DecodeError(_)) => (), - Err(_) => break, - } - } + let mut tags = Tag::read_from_path(tempname)?; + let mut streaminfo = tags.get_streaminfo().unwrap().clone(); + streaminfo.md5 = hasher.finalize()[..].to_vec(); + tags.set_streaminfo(streaminfo); + tags.save()?; - match enc.finish() { - Ok(_) => Ok(()), - Err(enc) => Err(anyhow!("Encoding failed:\t{:?}", enc.state())), - } + Ok(()) } |
