From c5537b6a606442fb846a46027b5210a73d0dd943 Mon Sep 17 00:00:00 2001 From: jaby Date: Thu, 21 Nov 2024 21:07:45 +0000 Subject: [PATCH] Something playing! --- src/Tools/psxfileconv/src/audio/my_xa/mod.rs | 2 +- .../src/audio/my_xa/xa_audio/mod.rs | 34 +++------ .../src/audio/my_xa/xa_audio/xapcm.rs | 71 +++++++++++++++---- 3 files changed, 66 insertions(+), 41 deletions(-) diff --git a/src/Tools/psxfileconv/src/audio/my_xa/mod.rs b/src/Tools/psxfileconv/src/audio/my_xa/mod.rs index 78124203..a20c974f 100644 --- a/src/Tools/psxfileconv/src/audio/my_xa/mod.rs +++ b/src/Tools/psxfileconv/src/audio/my_xa/mod.rs @@ -5,7 +5,7 @@ use clap::{Args, ValueEnum}; use std::io::Write; use tool_helper::{Error, Input}; -#[derive(Args)] +#[derive(Args, Clone)] pub struct Arguments { #[clap(value_enum, value_parser, default_value_t=Frequency::High)] frequency: Frequency, 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 54a350a0..8aa1ac76 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 @@ -1,14 +1,11 @@ mod xapcm; -use crate::audio::my_xa::Orality; - use super::Arguments; use super::raw_audio::{I16Samples, Settings}; use std::io::Write; use symphonia::core::audio::Layout; use tool_helper::Error; -const BLOCKS_PER_SECTOR:usize = 18; const HIGH_FREQUENCY:u32 = 37_800; const LOW_FREQUENCY:u32 = 18_900; @@ -26,31 +23,16 @@ pub fn audio_conversion_settings(arguments: &Arguments) -> Settings { } pub fn encode(input: I16Samples, output: &mut dyn Write, arguments: &Arguments) -> Result<(), Error> { - let mut encoder = xapcm::Encoder::default(); - let (samples_per_block, sample_count) = init_values(&input, arguments); + let mut encoder = xapcm::Encoder::new(&input, arguments.clone()); + let mut sector_count = 0; - for (sector, iteration) in (0..sample_count).step_by(samples_per_block).enumerate() { - let mut block = [0u8; 0x914]; - let slice = &input[sector..(sector + samples_per_block)]; + while let Some(xa_sector) = encoder.encode_next_xa_sector()? { + output.write(&xa_sector)?; - encoder.encode_xa(slice, (sample_count - sector) as i32, &mut block, arguments)?; - - print!("\rSector: {}; Sample_id: {}", sector, iteration); + sector_count += 1; + print!("\rSector: {} written", sector_count); } println!(); - Err(Error::not_implemented("XA conversion")) -} - -fn init_values(input: &I16Samples, arguments: &Arguments) -> (usize, usize) { - let samples_per_block = match arguments.sample_depth { - super::SampleDepth::Normal => 224, - super::SampleDepth::High => 112, - }; - - let sample_count = match arguments.orality { - super::Orality::Stereo => input.len()/2, - super::Orality::Mono => input.len(), - }; - - (samples_per_block as usize, sample_count) + //Err(Error::not_implemented("XA conversion")) + Ok(()) } \ No newline at end of file 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 4bbc4992..8490e89c 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,24 +1,59 @@ use crate::audio::my_xa::{Arguments, Orality, SampleDepth}; use tool_helper::Error; -pub struct Encoder { - left: ChannelState, - right: ChannelState +pub struct Encoder<'a> { + left: ChannelState, + right: ChannelState, + source: &'a[i16], + arguments: Arguments, + samples_per_block: i32, + sample_limit: i32 } -impl Encoder { +impl<'a> Encoder<'a> { + const BLOCKS_PER_SECTOR:usize = 18; const XA_ADPCM_FILTER_COUNT: i32 = 4; - const FILTER_K1: [i16; 5] = [0, 60, 115, 98, 122]; - const FILTER_K2: [i16; 5] = [0, 0, -52, -55, -60]; + const FILTER_K1: [i16; 5] = [0, 60, 115, 98, 122]; + const FILTER_K2: [i16; 5] = [0, 0, -52, -55, -60]; - pub fn encode_xa(&mut self, samples: &[i16], sample_limit: i32, data: &mut [u8], args: &Arguments) -> Result<(), Error> { + pub fn new(source: &[i16], arguments: Arguments) -> Encoder { + let (samples_per_block, sample_limit) = Self::samples_per_block_and_limit(&source, &arguments); + Encoder{left: ChannelState::default(), right: ChannelState::default(), source, arguments, samples_per_block, sample_limit} + } + + pub fn encode_next_xa_sector(&mut self) -> Result, Error> { + if self.source.is_empty() { + return Ok(None); + } + + let mut sector = [0u8; 0x930]; + sector[0x12] = 0x24 | 0x40; + sector[0x13] = 1 | 0 | 0; + + let mut dst = &mut sector[0x18..]; + for _ in 0..Self::BLOCKS_PER_SECTOR { + if self.source.len() < self.samples_per_block as usize { + break; + } + + self.encode_xa(&self.source[0..], self.sample_limit, dst)?; + + self.sample_limit -= self.samples_per_block; + self.source = &self.source[self.samples_per_block as usize..]; + dst = &mut dst[0x80..]; + } + + Ok(Some(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; let channels = [&mut self.left, &mut self.right]; - match args.sample_depth { + match self.arguments.sample_depth { SampleDepth::Normal => { - let (modulo, offset) = if args.orality == Orality::Stereo {(2, &STEREO_4BIT)} else {(1, &MONO_4BIT)}; + let (modulo, offset) = if self.arguments.orality == Orality::Stereo {(2, &STEREO_4BIT)} else {(1, &MONO_4BIT)}; let (first_offset, second_offset) = offset; for (offset_idx, offset_set) in [first_offset, second_offset].iter().enumerate() { @@ -30,7 +65,7 @@ impl Encoder { } }, SampleDepth::High => { - let (modulo, offset_set) = if args.orality == Orality::Stereo {(2, &STEREO_8BIT)} else {(1, &MONO_8BIT)}; + let (modulo, offset_set) = if self.arguments.orality == Orality::Stereo {(2, &STEREO_8BIT)} else {(1, &MONO_8BIT)}; for (idx, offset) in offset_set.iter().enumerate() { let byte = Self::encode(channels[idx%modulo], &samples[offset.sample..], sample_limit + offset.sample_limit, offset.pitch, &mut data[offset.data..], offset.data_shift, offset.data_pitch, Self::XA_ADPCM_FILTER_COUNT, SHIFT_RANGE_8BPS)?; data[idx] = byte; @@ -170,11 +205,19 @@ impl Encoder { Err(Error::from_text(format!("0 <= {} && {} <= {} was not satisfied with min_shift: {}", min_shift, min_shift, shift_range, min_shift))) } } -} -impl std::default::Default for Encoder { - fn default() -> Self { - Encoder{left: ChannelState::default(), right: ChannelState::default()} + fn samples_per_block_and_limit(input: &[i16], arguments: &Arguments) -> (i32, i32) { + let samples_per_block = match arguments.sample_depth { + SampleDepth::Normal => 224, + SampleDepth::High => 112, + }; + + let sample_limit = match arguments.orality { + Orality::Stereo => input.len()*2, + Orality::Mono => input.len(), + }; + + (samples_per_block, sample_limit as i32) } }