diff --git a/src/Tools/psxfileconv/src/audio/my_xa/mod.rs b/src/Tools/psxfileconv/src/audio/my_xa/mod.rs index d2c30cea..82d57f46 100644 --- a/src/Tools/psxfileconv/src/audio/my_xa/mod.rs +++ b/src/Tools/psxfileconv/src/audio/my_xa/mod.rs @@ -1,18 +1,9 @@ mod raw_audio; use std::io::Write; -use symphonia::core::audio::SampleBuffer; use tool_helper::{Error, Input}; -use symphonia::core::codecs::{DecoderOptions, CODEC_TYPE_NULL}; -use symphonia::core::errors::Error as SymError; -use symphonia::core::formats::FormatOptions; -use symphonia::core::io::MediaSourceStream; -use symphonia::core::meta::MetadataOptions; -use symphonia::core::probe::Hint; - pub fn convert(input: Input, _output: &mut dyn Write) -> Result<(), Error> { - raw_audio::load_raw_audio(input)?; - + let _prepared_xa_audio = raw_audio::load_for_xa_audio(input)?; Err(Error::not_implemented("XA conversion")) } \ No newline at end of file diff --git a/src/Tools/psxfileconv/src/audio/my_xa/raw_audio.rs b/src/Tools/psxfileconv/src/audio/my_xa/raw_audio.rs deleted file mode 100644 index 2e6e04ea..00000000 --- a/src/Tools/psxfileconv/src/audio/my_xa/raw_audio.rs +++ /dev/null @@ -1,80 +0,0 @@ -use std::io::Write; -use clap::error::ErrorKind; -use symphonia::core::audio::SampleBuffer; -use tool_helper::{Error, Input}; - -use symphonia::core::codecs::{DecoderOptions, CODEC_TYPE_NULL}; -use symphonia::core::errors::Error as SymError; -use symphonia::core::formats::FormatOptions; -use symphonia::core::io::MediaSourceStream; -use symphonia::core::meta::MetadataOptions; -use symphonia::core::probe::Hint; - -pub struct RawAudio { - -} - -pub fn load_raw_audio(input: Input) -> Result { - let media_stream = MediaSourceStream::new(Box::new(load_to_ram(input)?), Default::default()); - let probed = symphonia::default::get_probe().format(&Hint::new(), media_stream, &FormatOptions::default(), &MetadataOptions::default()).expect("unsupported format"); - let mut format = probed.format; - let track = format.tracks().iter().find(|t| t.codec_params.codec != CODEC_TYPE_NULL).expect("no supported audio tracks"); - - // Use the default options for the decoder. - let dec_opts: DecoderOptions = Default::default(); - - // Create a decoder for the track. - let mut decoder = symphonia::default::get_codecs().make(&track.codec_params, &dec_opts).expect("unsupported codec"); - - // Store the track identifier, it will be used to filter packets. - let track_id = track.id; - - // The decode loop. - loop { - // Get the next packet from the media format. - let packet = match format.next_packet() { - Ok(packet) => packet, - Err(SymError::ResetRequired) => { - return Err(Error::not_implemented("Miau")); - } - Err(SymError::IoError(err)) => { - // A unrecoverable error occurred, halt decoding. - if err.kind() == std::io::ErrorKind::UnexpectedEof { - return Err(Error::not_implemented("Miau2")); - } - - else { - panic!("{}", err); - } - } - Err(err) => { - // A unrecoverable error occurred, halt decoding. - panic!("{}", err); - } - }; - - // Consume any new metadata that has been read since the last packet. - while !format.metadata().is_latest() { - // Pop the old head of the metadata queue. - format.metadata().pop(); - - // Consume the new metadata at the head of the metadata queue. - } - - // If the packet does not belong to the selected track, skip over it. - if packet.track_id() != track_id { - continue; - } - - // Decode the packet into audio samples. - let packet = decoder.decode(&packet).expect("Urgh"); - println!(">>>"); - } -} - -fn load_to_ram(mut input: Input) -> Result>, Error> { - let mut buffer = Vec::default(); - - input.read_to_end(&mut buffer)?; - Ok(std::io::Cursor::new(buffer)) -} \ No newline at end of file diff --git a/src/Tools/psxfileconv/src/audio/my_xa/raw_audio/error.rs b/src/Tools/psxfileconv/src/audio/my_xa/raw_audio/error.rs new file mode 100644 index 00000000..668cbf2d --- /dev/null +++ b/src/Tools/psxfileconv/src/audio/my_xa/raw_audio/error.rs @@ -0,0 +1,30 @@ +use super::Error; +use symphonia::core::errors::Error as SymError; + +fn generic_map_error(action: &str, error: SymError) -> Error { + Error::from_text(format!("symphonia error: {} during {}", error, action)) +} + +pub fn probe(error: SymError) -> Error { + generic_map_error("probing of input", error) +} + +pub fn decoder(error: SymError) -> Error { + generic_map_error("finding codec", error) +} + +pub fn next_packet(error: SymError) -> Error { + generic_map_error("getting next raw packet", error) +} + +pub fn decode(error: SymError) -> Error { + generic_map_error("decoding of raw packet", error) +} + +pub fn find_track() -> Error { + Error::from_str("symphonia error: No audio track located") +} + +pub fn no_buffer_created() -> Error { + Error::from_str("No packets found for XA conversion") +} \ No newline at end of file diff --git a/src/Tools/psxfileconv/src/audio/my_xa/raw_audio/mod.rs b/src/Tools/psxfileconv/src/audio/my_xa/raw_audio/mod.rs new file mode 100644 index 00000000..9f164ef3 --- /dev/null +++ b/src/Tools/psxfileconv/src/audio/my_xa/raw_audio/mod.rs @@ -0,0 +1,70 @@ +mod error; + +use symphonia::core::audio::{RawSampleBuffer, SignalSpec}; +use symphonia::core::codecs::{Decoder, DecoderOptions, CODEC_TYPE_NULL}; +use symphonia::core::errors::Error as SymError; +use symphonia::core::formats::{FormatReader, FormatOptions}; +use symphonia::core::io::MediaSourceStream; +use symphonia::core::meta::MetadataOptions; +use symphonia::core::probe::Hint; +use tool_helper::{Error, Input}; + +type XASamples = RawSampleBuffer::; + +pub fn load_for_xa_audio(input: Input) -> Result { + let media_stream = MediaSourceStream::new(Box::new(load_to_ram(input)?), Default::default()); + let format = symphonia::default::get_probe().format(&Hint::new(), media_stream, &FormatOptions::default(), &MetadataOptions::default()).map_err(error::probe)?.format; + let track = format.tracks().iter().find(|t| t.codec_params.codec != CODEC_TYPE_NULL).ok_or_else(error::find_track)?; + + // Create a decoder for the track. + let decoder = symphonia::default::get_codecs().make(&track.codec_params, &DecoderOptions::default()).map_err(error::decoder)?; + let track_id = track.id; + + decode(format, decoder, track_id) +} + +fn decode(mut format: Box, mut decoder: Box, track_id: u32) -> Result { + let mut xa_audio = None; + + loop { + // Get the next packet from the media format. + let packet = match format.next_packet() { + Ok(packet) => packet, + Err(err) => { + if let SymError::IoError(io_err) = &err { + if io_err.kind() == std::io::ErrorKind::UnexpectedEof { + return xa_audio.ok_or_else(error::no_buffer_created); + } + } + return Err(error::next_packet(err)); + } + }; + + // Consume any new metadata that has been read since the last packet. + format.metadata().skip_to_latest(); + + // If the packet does not belong to the selected track, skip over it. + if packet.track_id() != track_id { + continue; + } + + // Decode the packet into audio samples. + let packet = decoder.decode(&packet).map_err(error::decode)?; + if xa_audio.is_none() { + let duration = packet.capacity() as u64; + + xa_audio = Some(XASamples::new(duration, SignalSpec::new_with_layout(44_100, symphonia::core::audio::Layout::Stereo))); + } + + if let Some(xa_audio) = &mut xa_audio { + xa_audio.copy_interleaved_ref(packet); + } + } +} + +fn load_to_ram(mut input: Input) -> Result>, Error> { + let mut buffer = Vec::default(); + + input.read_to_end(&mut buffer)?; + Ok(std::io::Cursor::new(buffer)) +} \ No newline at end of file