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 index d1572784..a3def9f1 100644 --- a/src/Tools/psxfileconv/src/audio/my_xa/raw_audio/mod.rs +++ b/src/Tools/psxfileconv/src/audio/my_xa/raw_audio/mod.rs @@ -1,7 +1,7 @@ mod error; use super::Frequency as RequestedFrequencyType; -use rubato::{FftFixedIn, Resampler}; +use rubato::{FftFixedInOut, Resampler}; use symphonia::core::{ audio::{Layout, SampleBuffer}, codecs::{Decoder, DecoderOptions, CODEC_TYPE_NULL}, @@ -28,55 +28,24 @@ impl Orality { } } -pub struct AudioSamples { - samples: Vec::, +pub struct PreparedAudioSamples { + samples: Vec::, orality: Orality, frequency: u32, } -impl AudioSamples { - pub fn new(samples: Vec, channels: usize, frequency: u32) -> Result, Error> { +impl PreparedAudioSamples { + pub fn new(samples: Vec, channels: usize, frequency: u32) -> Result { let orality = match channels { 0 => return Err(Error::from_str("Input file has no audio channels")), 1 => Orality::Mono, 2 => Orality::Stereo, _ => return Err(Error::from_str("Only Mono and Stereo input are supported")), }; - Ok(AudioSamples{samples, orality, frequency}) + Ok(PreparedAudioSamples{samples, orality, frequency}) } - // TODO: Reconsider passing zero_maker - pub fn to_planar(self, chunk_size: usize, zero_maker: fn()->T) -> Vec> { - let (_, chunk_remainder) = self.calculate_chunks(chunk_size); - let num_channel = self.orality.as_channels(); - let mut result = Vec::new(); - - for _ in 0..num_channel { - result.push(Vec::::new()); - } - - for (idx, sample) in self.samples.into_iter().enumerate() { - result[idx%num_channel].push(sample); - } - - for channel in &mut result { - println!("({} - {} = {})", chunk_size, chunk_remainder, chunk_size - chunk_remainder); - for _ in 0..(chunk_size - chunk_remainder) { - channel.push(zero_maker()); - } - } - - result - } - - pub fn calculate_chunks(&self, chunk_size: usize) -> (usize, usize) { - let sample_len = self.samples.len()/self.orality.as_channels(); - let div_value = chunk_size; - - (sample_len/div_value, sample_len%div_value) - } - - pub fn samples(&self) -> &Vec:: { + pub fn samples(&self) -> &Vec:: { &self.samples } @@ -91,21 +60,21 @@ struct InternalAudioSamples { } impl InternalAudioSamples { - pub fn new(planar_samples: Vec>, frequency: u32) -> InternalAudioSamples { - InternalAudioSamples{planar_samples, frequency} - } - - pub fn calculate_chunks(&self, chunk_size: usize) -> (usize, usize) { - if self.planar_samples.len() > 0 { - let sample_len = self.planar_samples[0].len(); - (sample_len/chunk_size, sample_len%chunk_size) + pub fn new(planar_samples: Vec>, frequency: u32) -> Result { + if planar_samples.len() < 1 { + // TODO: Make better text + Err(Error::from_str("Audio samples can not be empty")) } else { - (0, 0) + Ok(InternalAudioSamples{planar_samples, frequency}) } } + pub fn sample_len(&self) -> usize { + self.planar_samples[0].len() + } + pub fn channels(&self) -> usize { self.planar_samples.len() } @@ -120,29 +89,27 @@ impl InternalAudioSamples { } } -pub type PreparedAudioSamples = AudioSamples; - pub fn load_as_i16_audio(input: Input, freq_type: RequestedFrequencyType) -> Result { let raw_audio = load_raw_audio(input)?; let raw_audio = resample(raw_audio, 37_800)?; - test_write_wav(raw_audio)?; + test_write_wav(down_sample_interleave(raw_audio)?)?; Err(Error::not_implemented("Resampling not implemented")) } -fn test_write_wav(audio_samples: InternalAudioSamples) -> Result<(), Error> { - /*let spec = hound::WavSpec { +fn test_write_wav(audio_samples: PreparedAudioSamples) -> Result<(), Error> { + let spec = hound::WavSpec { channels: 2, sample_rate: 37_800, - bits_per_sample: 32, - sample_format: hound::SampleFormat::Float, + bits_per_sample: 16, + sample_format: hound::SampleFormat::Int, }; let mut file = hound::WavWriter::create("planschi.wav", spec).unwrap(); for sample in audio_samples.samples { file.write_sample(sample)?; } - file.finalize()?;*/ + file.finalize()?; Ok(()) } @@ -171,7 +138,7 @@ fn decode(mut format: Box, mut decoder: Box, trac Err(err) => { if let SymError::IoError(io_err) = &err { if io_err.kind() == std::io::ErrorKind::UnexpectedEof { - return Ok(InternalAudioSamples::new(samples, frequency)); + return InternalAudioSamples::new(samples, frequency); } } return Err(error::next_packet(err)); @@ -215,13 +182,21 @@ fn decode(mut format: Box, mut decoder: Box, trac fn resample(input: InternalAudioSamples, target_frequency: u32) -> Result { const HIGH_QUALITY_CHUNKS:usize = (1024*10)*100; - const SUB_CHUNKS:usize = 20; + fn process_partial(input_option: Option<&[&[f32]]>, resampler: &mut FftFixedInOut, planar_output: &mut Vec>) -> Result<(), Error> { + let new_samples = resampler.process_partial(input_option, None).map_err(error::resample)?; + for (channel, channel_samples) in new_samples.into_iter().enumerate() { + planar_output[channel].extend(channel_samples.iter()); + } + Ok(()) + } - let (chunk_size, sub_chunks) = (HIGH_QUALITY_CHUNKS, SUB_CHUNKS); - let (chunk_count, chunk_remainder) = input.calculate_chunks(chunk_size); - let mut planar_input = input.planar_slices(); - let mut resampler = FftFixedIn::::new(input.frequency as usize, target_frequency as usize, chunk_size, sub_chunks, input.channels()).map_err(error::resampler_construction)?; - let mut planar_output = { + let chunk_size = HIGH_QUALITY_CHUNKS; + let mut planar_input = input.planar_slices(); + let mut resampler = FftFixedInOut::::new(input.frequency as usize, target_frequency as usize, chunk_size, input.channels()).map_err(error::resampler_construction)?; + let delay = resampler.output_delay(); + let mut sample_len = input.sample_len(); + let new_sample_len = (sample_len as f64*(target_frequency as f64/input.frequency as f64)) as usize; + let mut planar_output = { let mut planar_output = Vec::new(); for _ in 0..planar_input.len() { @@ -230,27 +205,34 @@ fn resample(input: InternalAudioSamples, target_frequency: u32) -> Result sample_len { + if sample_len > 0 { + // Still frames left + process_partial(Some(&planar_input), &mut resampler, &mut planar_output)?; + } + break; + } + let new_samples = resampler.process(&planar_input, None).map_err(error::resample)?; for (channel, slice) in planar_input.iter_mut().enumerate() { - *slice = &slice[chunk_size..]; + *slice = &slice[next_input_frames..]; planar_output[channel].extend(new_samples[channel].iter()); } + sample_len -= next_input_frames; } - let mut process_partial = |input_option: Option<&[&[f32]]>| -> Result<(), Error> { - let new_samples = resampler.process_partial(input_option, None).map_err(error::resample)?; - for (channel, channel_samples) in new_samples.into_iter().enumerate() { - planar_output[channel].extend(channel_samples.iter()); - } - - Ok(()) - }; - - if chunk_remainder > 0 { - process_partial(Some(&planar_input))?; + if planar_output[0].len() < delay + new_sample_len { + // Flush + process_partial(None, &mut resampler, &mut planar_output)?; + } + + for channel in &mut planar_output { + let start = delay; + let end = start + new_sample_len; + *channel = channel[start..end].into(); } - process_partial(None)?; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// let spec = hound::WavSpec { @@ -266,8 +248,11 @@ fn resample(input: InternalAudioSamples, target_frequency: u32) -> Result Result { + Err(Error::not_implemented("down_sample_interleave")) } fn load_to_ram(mut input: Input) -> Result>, Error> {