summaryrefslogtreecommitdiff
path: root/src/flac
diff options
context:
space:
mode:
Diffstat (limited to 'src/flac')
-rw-r--r--src/flac/decoder.rs139
-rw-r--r--src/flac/mod.rs311
2 files changed, 0 insertions, 450 deletions
diff --git a/src/flac/decoder.rs b/src/flac/decoder.rs
deleted file mode 100644
index 99ac36e..0000000
--- a/src/flac/decoder.rs
+++ /dev/null
@@ -1,139 +0,0 @@
-use std::{
- error::Error,
- ffi::{CString, c_void},
- fmt::Display,
- path::Path,
-};
-
-use libflac_sys::{
- FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED,
- FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE,
- FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS,
- FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR, FLAC__STREAM_DECODER_INIT_STATUS_OK,
- FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER, FLAC__StreamDecoder,
- FLAC__StreamDecoderInitStatus, FLAC__bool, FLAC__stream_decoder_finish,
- FLAC__stream_decoder_get_bits_per_sample, FLAC__stream_decoder_get_channels,
- FLAC__stream_decoder_get_sample_rate, FLAC__stream_decoder_init_file, FLAC__stream_decoder_new,
- FLAC__stream_decoder_process_single, FLAC__stream_decoder_set_md5_checking,
-};
-
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
-#[repr(u32)]
-pub enum FlacDecoderInitError {
- AlreadyInitialized = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED,
-
- ErrorOpeningFile = FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE,
-
- InvalidCallbacks = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS,
-
- MemoryAllocationError = FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR,
-
- UnsupportedContainer = FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER,
-}
-
-impl Error for FlacDecoderInitError {}
-
-impl Display for FlacDecoderInitError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{self:?}")
- }
-}
-
-impl From<FlacDecoderInitError> for FLAC__StreamDecoderInitStatus {
- fn from(val: FlacDecoderInitError) -> Self {
- val as FLAC__StreamDecoderInitStatus
- }
-}
-
-impl TryFrom<FLAC__StreamDecoderInitStatus> for FlacDecoderInitError {
- type Error = ();
-
- #[allow(non_upper_case_globals)]
- fn try_from(raw: FLAC__StreamDecoderInitStatus) -> Result<FlacDecoderInitError, ()> {
- Ok(match raw {
- FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED => {
- FlacDecoderInitError::AlreadyInitialized
- }
- FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE => {
- FlacDecoderInitError::ErrorOpeningFile
- }
- FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS => {
- FlacDecoderInitError::InvalidCallbacks
- }
- FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR => {
- FlacDecoderInitError::MemoryAllocationError
- }
- FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER => {
- FlacDecoderInitError::UnsupportedContainer
- }
- _ => return Err(()),
- })
- }
-}
-
-fn convert_path(path: &Path) -> CString {
- CString::new(path.to_str().expect("non-UTF-8 filename")).expect("filename has internal NULs")
-}
-
-pub(crate) struct FlacDecoder(pub *mut FLAC__StreamDecoder);
-
-impl FlacDecoder {
- pub(crate) fn new() -> Self {
- FlacDecoder(unsafe { FLAC__stream_decoder_new() })
- }
-
- pub(crate) fn init_decode_from_file<P: AsRef<Path>>(
- &self,
- file: &P,
- buf: &mut Vec<i32>,
- ) -> Result<(), FlacDecoderInitError> {
- unsafe {
- FLAC__stream_decoder_set_md5_checking(self.0, true as FLAC__bool);
- }
-
- let filename = convert_path(file.as_ref());
- unsafe {
- let result: FLAC__StreamDecoderInitStatus = FLAC__stream_decoder_init_file(
- self.0,
- filename.as_ptr(),
- None,
- None,
- None,
- buf.as_mut_ptr() as *mut c_void,
- );
- if result != FLAC__STREAM_DECODER_INIT_STATUS_OK {
- return Err(FlacDecoderInitError::try_from(result).unwrap());
- }
- }
-
- Ok(())
- }
-
- pub(crate) fn decode_frame(&self) -> Result<(), ()> {
- if unsafe { FLAC__stream_decoder_process_single(self.0) } != 0 {
- Ok(())
- } else {
- Err(())
- }
- }
-
- pub(crate) fn get_channels(&self) -> u32 {
- unsafe { FLAC__stream_decoder_get_channels(self.0) }
- }
-
- pub(crate) fn get_bps(&self) -> u32 {
- unsafe { FLAC__stream_decoder_get_bits_per_sample(self.0) }
- }
-
- pub(crate) fn get_samplerate(&self) -> u32 {
- unsafe { FLAC__stream_decoder_get_sample_rate(self.0) }
- }
-}
-
-impl Drop for FlacDecoder {
- fn drop(&mut self) {
- if !(self.0.is_null()) {
- unsafe { FLAC__stream_decoder_finish(self.0) };
- }
- }
-}
diff --git a/src/flac/mod.rs b/src/flac/mod.rs
deleted file mode 100644
index 7a79e44..0000000
--- a/src/flac/mod.rs
+++ /dev/null
@@ -1,311 +0,0 @@
-mod decoder;
-
-use anyhow::{Result, anyhow};
-use flac_bound::{FlacEncoder, WriteWrapper};
-/* use md5::Digest; */
-use metaflac::Tag;
-use std::{fs::File, path::Path};
-
-use crate::flac::decoder::FlacDecoder;
-
-pub const CURRENT_VENDOR: &str = "reference libFLAC 1.5.0 20250211";
-
-/* type BoxedFormatReader = Box<dyn FormatReader>;
-type BoxedAudioDecoder = Box<dyn AudioDecoder + 'static>; */
-
-/* pub struct StreamConfig {
- channels: u32,
- bits_per_sample: Bps,
- sample_rate: u32,
-}
-
-pub 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,
- }
- }
-} */
-
-/* struct FileEncoder {
- filename: PathBuf,
- streamdata: StreamConfig,
- format: BoxedFormatReader,
- decoder: BoxedAudioDecoder,
-}
-
-impl FileEncoder {
- fn new(file: impl AsRef<Path>) -> Result<Self> {
- let (format, decoder, config) = init_decoder(&file)?;
- Ok(FileEncoder {
- filename: file.as_ref().to_path_buf(),
- streamdata: config,
- format,
- decoder,
- })
- }
-
- fn temp_name(&self) -> PathBuf {
- self.filename.clone().with_extension("tmp")
- }
-
- fn encode(&mut self, mut encoder: FlacEncoder) -> Result<Vec<u8>> {
- let mut buffer: Vec<i32> = Vec::new();
- let mut hasher = Md5::new();
- let track_id = self.format.default_track(TrackType::Audio).unwrap().id;
- let offset = self.streamdata.bits_per_sample.value();
-
- loop {
- let packet = match self.format.next_packet() {
- Ok(Some(packet)) => packet,
- Ok(None) => break,
- Err(error) => return Err(error.into()),
- };
-
- if packet.track_id() != track_id {
- continue;
- }
-
- if let GenericAudioBufferRef::S32(buf) = self.decoder.decode(&packet)? {
- for sample in buf.iter_interleaved() {
- let mut real_sample = sample;
- if offset != 32 {
- real_sample = sample >> (32 - offset)
- }
- match offset {
- 16 => hasher.update(i16::try_from(real_sample)?.to_le_bytes()),
- 24 => hasher
- .update(i24::i24::try_from_i32(real_sample).unwrap().to_le_bytes()),
- _ => hasher.update(real_sample.to_le_bytes()),
- }
- buffer.push(real_sample);
- }
- encoder
- .process_interleaved(&buffer, buf.samples_planar() as u32)
- .unwrap();
- buffer.clear();
- } else {
- return Err(anyhow!("unsupported codec"));
- }
- }
-
- if let Err(enc) = encoder.finish() {
- return Err(anyhow!("Encoding failed:\t{:?}", enc.state()));
- }
-
- Ok(hasher.finalize().to_vec())
- }
-
- fn write_tags(&self, hash: Vec<u8>) -> Result<()> {
- let tags = Tag::read_from_path(&self.filename)?;
- let mut output = Tag::read_from_path(self.temp_name())?;
-
- let mut streaminfo = tags.get_streaminfo().unwrap().clone();
-
- streaminfo.md5 = hash;
- output.set_streaminfo(streaminfo);
-
- for block in tags.blocks() {
- match block {
- Block::VorbisComment(comment) => {
- for (key, val) in comment.comments.clone() {
- if key != "ENCODER" {
- output.set_vorbis(key, val);
- }
- }
- }
- Block::StreamInfo(_) | Block::Padding(_) => {}
- _ => output.push_block(block.clone()),
- }
- }
-
- output.write_to_path(self.temp_name())?;
- Ok(())
- }
-}
-
-fn init_decoder(
- filename: impl AsRef<Path>,
-) -> Result<(BoxedFormatReader, BoxedAudioDecoder, StreamConfig)> {
- let src = std::fs::File::open(filename)?;
- let mss = MediaSourceStream::new(Box::new(src), Default::default());
- let mut hint = Hint::new();
- hint.with_extension("flac");
-
- let format_opts: FormatOptions = Default::default();
- let metadata_opts: MetadataOptions = Default::default();
-
- let format = symphonia::default::get_probe()
- .probe(&hint, mss, format_opts, metadata_opts)
- .unwrap();
-
- let track = format.default_track(TrackType::Audio).unwrap();
-
- let decoder = symphonia::default::get_codecs()
- .make_audio_decoder(
- track.codec_params.as_ref().unwrap().audio().unwrap(),
- &Default::default(),
- )
- .unwrap();
-
- let params = track.codec_params.as_ref().unwrap().audio().unwrap();
-
- let config = StreamConfig {
- 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(),
- };
-
- Ok((format, decoder, config))
-} */
-
-pub fn encode_file(filename: impl AsRef<Path>) -> Result<()> {
- /* let mut filencoder = FileEncoder::new(filename)?;
- let temp_name = filencoder.temp_name();
-
- if temp_name.exists() {
- std::fs::remove_file(&temp_name)?;
- }
-
- let mut outf = File::create(temp_name)?;
- let mut outw = WriteWrapper(&mut outf);
- let enc = FlacEncoder::new()
- .unwrap()
- .channels(filencoder.streamdata.channels)
- .bits_per_sample(filencoder.streamdata.bits_per_sample.value())
- .sample_rate(filencoder.streamdata.sample_rate)
- .compression_level(8)
- .verify(false)
- .init_write(&mut outw)
- .unwrap();
-
- let hash = filencoder.encode(enc)?;
- filencoder.write_tags(hash)?;
- std::fs::rename(filencoder.temp_name(), filencoder.filename)?;
- Ok(()) */
-
- let decoder = FlacDecoder::new();
- let mut buffer: Vec<i32> = Vec::new();
- decoder.init_decode_from_file(&filename, &mut buffer)?;
-
- let temp_name = filename.as_ref().with_extension("tmp");
- let mut outf = File::create(temp_name)?;
- let mut outw = WriteWrapper(&mut outf);
- let mut enc = FlacEncoder::new()
- .unwrap()
- .channels(decoder.get_channels())
- .bits_per_sample(decoder.get_bps())
- .sample_rate(decoder.get_samplerate())
- .compression_level(8)
- .verify(false)
- .init_write(&mut outw)
- .unwrap();
-
- while decoder.decode_frame().is_ok() {
- enc.process_interleaved(&buffer, buffer.iter().len() as u32 / decoder.get_channels())
- .unwrap();
- buffer.clear();
- }
-
- todo!()
-}
-
-pub fn get_vendor(file: impl AsRef<Path>) -> Result<String> {
- if let Some(vorbis) = Tag::read_from_path(file)?.vorbis_comments() {
- Ok(vorbis.vendor_string.to_owned())
- } else {
- Err(anyhow!("Vendor string not found"))
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use metaflac::Tag;
-
- #[test]
- fn bit16() {
- let name = "16bit.flac";
- let tempname = "16bit.flac.temp";
- std::fs::copy(name, tempname).unwrap();
- encode_file(name).unwrap();
- let target_md5 = Tag::read_from_path(tempname)
- .unwrap()
- .get_streaminfo()
- .unwrap()
- .md5
- .clone();
- let encoded_md5 = Tag::read_from_path(name)
- .unwrap()
- .get_streaminfo()
- .unwrap()
- .md5
- .clone();
- std::fs::remove_file(name).unwrap();
- std::fs::rename(tempname, name).unwrap();
- assert_eq!(target_md5, encoded_md5);
- }
-
- #[test]
- fn bit24() {
- let name = "24bit.flac";
- let tempname = "24bit.flac.temp";
- std::fs::copy(name, tempname).unwrap();
- encode_file(name).unwrap();
- let target_md5 = Tag::read_from_path(tempname)
- .unwrap()
- .get_streaminfo()
- .unwrap()
- .md5
- .clone();
- let encoded_md5 = Tag::read_from_path(name)
- .unwrap()
- .get_streaminfo()
- .unwrap()
- .md5
- .clone();
- std::fs::remove_file(name).unwrap();
- std::fs::rename(tempname, name).unwrap();
- assert_eq!(target_md5, encoded_md5);
- }
-
- #[test]
- fn bit32() {
- let name = "32bit.flac";
- let tempname = "32bit.flac.temp";
- std::fs::copy(name, tempname).unwrap();
- encode_file(name).unwrap();
- let target_md5 = Tag::read_from_path(tempname)
- .unwrap()
- .get_streaminfo()
- .unwrap()
- .md5
- .clone();
- let encoded_md5 = Tag::read_from_path(name)
- .unwrap()
- .get_streaminfo()
- .unwrap()
- .md5
- .clone();
- std::fs::remove_file(name).unwrap();
- std::fs::rename(tempname, name).unwrap();
- assert_eq!(target_md5, encoded_md5);
- }
-}