Clean up my-xa
This commit is contained in:
parent
5244786347
commit
23162d47ea
|
@ -8,6 +8,7 @@ panic = "abort"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "2.6.0"
|
bitflags = "2.6.0"
|
||||||
|
cdtypes = {path = "../cdtypes"}
|
||||||
clap = {version = "4.4.11", features = ["derive"]}
|
clap = {version = "4.4.11", features = ["derive"]}
|
||||||
image = "0.24.7"
|
image = "0.24.7"
|
||||||
hound = "3.5.1"
|
hound = "3.5.1"
|
||||||
|
|
|
@ -8,9 +8,9 @@ use xa_audio::{LOW_FREQUENCY, HIGH_FREQUENCY};
|
||||||
|
|
||||||
#[derive(Args, Clone)]
|
#[derive(Args, Clone)]
|
||||||
pub struct Arguments {
|
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,
|
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,
|
sample_depth: SampleDepth,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ mod xapcm;
|
||||||
|
|
||||||
use super::Arguments;
|
use super::Arguments;
|
||||||
use super::raw_audio::CDAudioSamples;
|
use super::raw_audio::CDAudioSamples;
|
||||||
|
use cdtypes::types::sector::{Mode2Form2, SECTOR_SIZE};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use tool_helper::Error;
|
use tool_helper::Error;
|
||||||
|
|
||||||
|
@ -9,9 +10,10 @@ pub const HIGH_FREQUENCY:u32 = 37_800;
|
||||||
pub const LOW_FREQUENCY:u32 = 18_900;
|
pub const LOW_FREQUENCY:u32 = 18_900;
|
||||||
|
|
||||||
pub fn encode(input: CDAudioSamples, output: &mut dyn Write, arguments: &Arguments) -> Result<(), Error> {
|
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()? {
|
while let Some(xa_sector) = encoder.encode_next_xa_sector()? {
|
||||||
|
let xa_sector = unsafe {std::mem::transmute::<Mode2Form2, [u8; SECTOR_SIZE]>(xa_sector)};
|
||||||
output.write(&xa_sector)?;
|
output.write(&xa_sector)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -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;
|
use tool_helper::Error;
|
||||||
|
|
||||||
pub struct Encoder<'a> {
|
pub struct Encoder<'a> {
|
||||||
left: ChannelState,
|
left: ChannelState,
|
||||||
right: ChannelState,
|
right: ChannelState,
|
||||||
source: &'a[i16],
|
source: &'a[i16],
|
||||||
|
frequency: Frequency,
|
||||||
sample_depth: SampleDepth,
|
sample_depth: SampleDepth,
|
||||||
orality: Orality,
|
orality: Orality,
|
||||||
samples_per_block: i32,
|
samples_per_block: i32,
|
||||||
|
@ -17,31 +19,21 @@ impl<'a> Encoder<'a> {
|
||||||
const FILTER_K1: [i16; 5] = [0, 60, 115, 98, 122];
|
const FILTER_K1: [i16; 5] = [0, 60, 115, 98, 122];
|
||||||
const FILTER_K2: [i16; 5] = [0, 0, -52, -55, -60];
|
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 orality = cd_sample.orality();
|
||||||
let (samples_per_block, sample_limit) = Self::samples_per_block_and_limit(&cd_sample.samples(), sample_depth, 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<Option<[u8; 0x930]>, Error> {
|
pub fn encode_next_xa_sector(&mut self) -> Result<Option<Mode2Form2>, Error> {
|
||||||
if self.source.is_empty() {
|
if self.source.is_empty() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut sector = [0u8; 0x930];
|
let mut sector = self.create_new_sector();
|
||||||
for i in 0..10 {
|
let mut dst = &mut sector.data[0..];
|
||||||
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 dst = &mut sector[0x18..];
|
|
||||||
for _ in 0..Self::BLOCKS_PER_SECTOR {
|
for _ in 0..Self::BLOCKS_PER_SECTOR {
|
||||||
if self.source.len() < self.samples_per_block as usize {
|
if self.source.len() < self.samples_per_block as usize {
|
||||||
self.source = &self.source[self.source.len()..];
|
self.source = &self.source[self.source.len()..];
|
||||||
|
@ -55,9 +47,33 @@ impl<'a> Encoder<'a> {
|
||||||
dst = &mut dst[0x80..];
|
dst = &mut dst[0x80..];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sector.finalize();
|
||||||
Ok(Some(sector))
|
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> {
|
fn encode_xa(&mut self, samples: &[i16], sample_limit: i32, data: &mut [u8]) -> Result<(), Error> {
|
||||||
const SHIFT_RANGE_4BPS: i32 = 12;
|
const SHIFT_RANGE_4BPS: i32 = 12;
|
||||||
const SHIFT_RANGE_8BPS: i32 = 8;
|
const SHIFT_RANGE_8BPS: i32 = 8;
|
||||||
|
|
Loading…
Reference in New Issue