diff --git a/src/Tools/psxfileconv/Cargo.toml b/src/Tools/psxfileconv/Cargo.toml index d8799622..1a5aeb3a 100644 --- a/src/Tools/psxfileconv/Cargo.toml +++ b/src/Tools/psxfileconv/Cargo.toml @@ -8,6 +8,7 @@ panic = "abort" [dependencies] bitflags = "2.6.0" +cdtypes = {path = "../cdtypes"} clap = {version = "4.4.11", features = ["derive"]} image = "0.24.7" hound = "3.5.1" diff --git a/src/Tools/psxfileconv/src/audio/my_xa/mod.rs b/src/Tools/psxfileconv/src/audio/my_xa/mod.rs index aa93712b..f34dc4c2 100644 --- a/src/Tools/psxfileconv/src/audio/my_xa/mod.rs +++ b/src/Tools/psxfileconv/src/audio/my_xa/mod.rs @@ -8,9 +8,9 @@ use xa_audio::{LOW_FREQUENCY, HIGH_FREQUENCY}; #[derive(Args, Clone)] pub struct Arguments { - #[clap(value_enum, value_parser, default_value_t=Frequency::High)] + #[clap(short='f', long="frequency", value_enum, value_parser, default_value_t=Frequency::High)] frequency: Frequency, - #[clap(value_enum, value_parser, default_value_t=SampleDepth::Normal)] + #[clap(short='b', long="bitdepth", value_enum, value_parser, default_value_t=SampleDepth::Normal)] sample_depth: SampleDepth, } diff --git a/src/Tools/psxfileconv/src/audio/my_xa/xa_audio/mod.rs b/src/Tools/psxfileconv/src/audio/my_xa/xa_audio/mod.rs index cdc7ad1c..f6764021 100644 --- a/src/Tools/psxfileconv/src/audio/my_xa/xa_audio/mod.rs +++ b/src/Tools/psxfileconv/src/audio/my_xa/xa_audio/mod.rs @@ -2,6 +2,7 @@ mod xapcm; use super::Arguments; use super::raw_audio::CDAudioSamples; +use cdtypes::types::sector::{Mode2Form2, SECTOR_SIZE}; use std::io::Write; use tool_helper::Error; @@ -9,9 +10,10 @@ pub const HIGH_FREQUENCY:u32 = 37_800; pub const LOW_FREQUENCY:u32 = 18_900; pub fn encode(input: CDAudioSamples, output: &mut dyn Write, arguments: &Arguments) -> Result<(), Error> { - let mut encoder = xapcm::Encoder::new(&input, arguments.sample_depth); + let mut encoder = xapcm::Encoder::new(&input, arguments.frequency, arguments.sample_depth); while let Some(xa_sector) = encoder.encode_next_xa_sector()? { + let xa_sector = unsafe {std::mem::transmute::(xa_sector)}; output.write(&xa_sector)?; } Ok(()) diff --git a/src/Tools/psxfileconv/src/audio/my_xa/xa_audio/xapcm.rs b/src/Tools/psxfileconv/src/audio/my_xa/xa_audio/xapcm.rs index fb2e3c65..e413d014 100644 --- a/src/Tools/psxfileconv/src/audio/my_xa/xa_audio/xapcm.rs +++ b/src/Tools/psxfileconv/src/audio/my_xa/xa_audio/xapcm.rs @@ -1,10 +1,12 @@ -use crate::audio::my_xa::{raw_audio::{CDAudioSamples, Orality}, SampleDepth}; +use crate::audio::my_xa::{raw_audio::{CDAudioSamples, Orality}, Frequency, SampleDepth}; +use cdtypes::types::sector::{Mode2Form2, XAADPCMBitsPerSample, XAADPCMSampleRate, XAADPCMSound}; use tool_helper::Error; pub struct Encoder<'a> { left: ChannelState, right: ChannelState, source: &'a[i16], + frequency: Frequency, sample_depth: SampleDepth, orality: Orality, samples_per_block: i32, @@ -17,31 +19,21 @@ impl<'a> Encoder<'a> { const FILTER_K1: [i16; 5] = [0, 60, 115, 98, 122]; const FILTER_K2: [i16; 5] = [0, 0, -52, -55, -60]; - pub fn new(cd_sample: &CDAudioSamples, sample_depth: SampleDepth) -> Encoder { + pub fn new(cd_sample: &CDAudioSamples, frequency: Frequency, sample_depth: SampleDepth) -> Encoder { let orality = cd_sample.orality(); let (samples_per_block, sample_limit) = Self::samples_per_block_and_limit(&cd_sample.samples(), sample_depth, orality); - Encoder{left: ChannelState::default(), right: ChannelState::default(), source: &cd_sample.samples(), sample_depth, orality, samples_per_block, sample_limit} + Encoder{left: ChannelState::default(), right: ChannelState::default(), source: &cd_sample.samples(), frequency, sample_depth, orality, samples_per_block, sample_limit} } - pub fn encode_next_xa_sector(&mut self) -> Result, Error> { + pub fn encode_next_xa_sector(&mut self) -> Result, Error> { if self.source.is_empty() { return Ok(None); } - let mut sector = [0u8; 0x930]; - for i in 0..10 { - sector[0x01+i] = 0xFF; - } - sector[0x0F] = 0x02; - - sector[0x12] = 0x24 | 0x40; - sector[0x13] = 1 | 0 | 0; // < TODO: Actually consider settings - for i in 0..4 { - sector[0x14+i] = sector[0x10+i]; - } + let mut sector = self.create_new_sector(); + let mut dst = &mut sector.data[0..]; - let mut dst = &mut sector[0x18..]; for _ in 0..Self::BLOCKS_PER_SECTOR { if self.source.len() < self.samples_per_block as usize { self.source = &self.source[self.source.len()..]; @@ -55,9 +47,33 @@ impl<'a> Encoder<'a> { dst = &mut dst[0x80..]; } + sector.finalize(); Ok(Some(sector)) } + fn create_new_sector(&self) -> Mode2Form2 { + let mut sector = Mode2Form2::new(); + let sub_mode = &mut sector.sub_header.sub_mode; + let coding_info = &mut sector.sub_header.coding_info; + + sub_mode.set_real_time(); + + coding_info.set_sound_type(match self.orality { + Orality::Mono => XAADPCMSound::Mono, + Orality::Stereo => XAADPCMSound::Stereo + }); + coding_info.set_sample_rate(match self.frequency { + Frequency::Low => XAADPCMSampleRate::Freq18900Hz, + Frequency::High => XAADPCMSampleRate::Freq37800Hz, + }); + coding_info.set_bits_per_sample(match self.sample_depth { + SampleDepth::Normal => XAADPCMBitsPerSample::Normal, + SampleDepth::High => XAADPCMBitsPerSample::High, + }); + + sector + } + fn encode_xa(&mut self, samples: &[i16], sample_limit: i32, data: &mut [u8]) -> Result<(), Error> { const SHIFT_RANGE_4BPS: i32 = 12; const SHIFT_RANGE_8BPS: i32 = 8;