Integrate all the progress into master #6
|
@ -1,9 +1,39 @@
|
|||
mod raw_audio;
|
||||
mod xa_audio;
|
||||
|
||||
use clap::{Args, ValueEnum};
|
||||
use std::io::Write;
|
||||
use tool_helper::{Error, Input};
|
||||
|
||||
pub fn convert(input: Input, _output: &mut dyn Write) -> Result<(), Error> {
|
||||
let _prepared_xa_audio = raw_audio::load_for_xa_audio(input)?;
|
||||
Err(Error::not_implemented("XA conversion"))
|
||||
#[derive(Args)]
|
||||
pub struct Arguments {
|
||||
#[clap(value_enum, value_parser, default_value_t=Frequency::High)]
|
||||
frequency: Frequency,
|
||||
#[clap(value_enum, value_parser, default_value_t=Channels::Stereo)]
|
||||
channels: Channels,
|
||||
#[clap(value_enum, value_parser, default_value_t=SampleDepth::Normal)]
|
||||
sample_depth: SampleDepth,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, ValueEnum)]
|
||||
pub enum Frequency {
|
||||
High,
|
||||
Low,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, ValueEnum)]
|
||||
pub enum Channels {
|
||||
Stereo,
|
||||
Mono,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, ValueEnum)]
|
||||
pub enum SampleDepth {
|
||||
Normal,
|
||||
High
|
||||
}
|
||||
|
||||
pub fn convert(args: Arguments, input: Input, output: &mut dyn Write) -> Result<(), Error> {
|
||||
let prepared_xa_audio = raw_audio::load_as_i16_audio(input, xa_audio::audio_conversion_settings(&args))?;
|
||||
xa_audio::convert(prepared_xa_audio, output, &args)
|
||||
}
|
|
@ -1,17 +1,28 @@
|
|||
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 symphonia::core::{
|
||||
audio::{Layout, SampleBuffer, SignalSpec},
|
||||
codecs::{Decoder, DecoderOptions, CODEC_TYPE_NULL},
|
||||
errors::Error as SymError,
|
||||
formats::{FormatReader, FormatOptions},
|
||||
io::MediaSourceStream,
|
||||
meta::MetadataOptions,
|
||||
probe::Hint
|
||||
};
|
||||
use tool_helper::{Error, Input};
|
||||
|
||||
type XASamples = RawSampleBuffer::<i16>;
|
||||
pub type I16Samples = SampleBuffer::<i16>;
|
||||
pub struct Settings {
|
||||
frequency: u32,
|
||||
layout: Layout
|
||||
}
|
||||
|
||||
pub fn load_for_xa_audio(input: Input) -> Result<XASamples, Error> {
|
||||
impl Settings {
|
||||
pub fn new(frequency: u32, layout: Layout) -> Settings {
|
||||
Settings{frequency, layout}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_as_i16_audio(input: Input, settings: Settings) -> Result<I16Samples, Error> {
|
||||
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)?;
|
||||
|
@ -20,11 +31,11 @@ pub fn load_for_xa_audio(input: Input) -> Result<XASamples, Error> {
|
|||
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)
|
||||
decode(format, decoder, settings, track_id)
|
||||
}
|
||||
|
||||
fn decode(mut format: Box<dyn FormatReader>, mut decoder: Box<dyn Decoder>, track_id: u32) -> Result<XASamples, Error> {
|
||||
let mut xa_audio = None;
|
||||
fn decode(mut format: Box<dyn FormatReader>, mut decoder: Box<dyn Decoder>, settings: Settings, track_id: u32) -> Result<I16Samples, Error> {
|
||||
let mut i16_audio = None;
|
||||
|
||||
loop {
|
||||
// Get the next packet from the media format.
|
||||
|
@ -33,7 +44,7 @@ fn decode(mut format: Box<dyn FormatReader>, mut decoder: Box<dyn Decoder>, trac
|
|||
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 i16_audio.ok_or_else(error::no_buffer_created);
|
||||
}
|
||||
}
|
||||
return Err(error::next_packet(err));
|
||||
|
@ -50,14 +61,14 @@ fn decode(mut format: Box<dyn FormatReader>, mut decoder: Box<dyn Decoder>, trac
|
|||
|
||||
// Decode the packet into audio samples.
|
||||
let packet = decoder.decode(&packet).map_err(error::decode)?;
|
||||
if xa_audio.is_none() {
|
||||
if i16_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)));
|
||||
i16_audio = Some(I16Samples::new(duration, SignalSpec::new_with_layout(settings.frequency, settings.layout)));
|
||||
}
|
||||
|
||||
if let Some(xa_audio) = &mut xa_audio {
|
||||
xa_audio.copy_interleaved_ref(packet);
|
||||
if let Some(i16_audio) = &mut i16_audio {
|
||||
i16_audio.copy_interleaved_ref(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
use super::Arguments;
|
||||
use super::raw_audio::{I16Samples, Settings};
|
||||
use std::io::Write;
|
||||
use symphonia::core::audio::Layout;
|
||||
use tool_helper::Error;
|
||||
|
||||
const HIGH_FREQUENCY:u32 = 37_800;
|
||||
const LOW_FREQUENCY:u32 = 18_900;
|
||||
|
||||
pub fn audio_conversion_settings(arguments: &Arguments) -> Settings {
|
||||
let frequency = match arguments.frequency {
|
||||
super::Frequency::High => HIGH_FREQUENCY,
|
||||
super::Frequency::Low => LOW_FREQUENCY,
|
||||
};
|
||||
let layout = match arguments.channels {
|
||||
super::Channels::Stereo => Layout::Stereo,
|
||||
super::Channels::Mono => Layout::Mono,
|
||||
};
|
||||
|
||||
Settings::new(frequency, layout)
|
||||
}
|
||||
|
||||
pub fn convert(_input: I16Samples, _output: &mut dyn Write, _arguments: &Arguments) -> Result<(), Error> {
|
||||
Err(Error::not_implemented("XA conversion"))
|
||||
}
|
|
@ -25,7 +25,7 @@ enum SubCommands {
|
|||
Nothing,
|
||||
SimpleTIM(reduced_tim::Arguments),
|
||||
VAG(vag::Arguments),
|
||||
MyXA,
|
||||
MyXA(my_xa::Arguments),
|
||||
|
||||
// === External Commands ===
|
||||
XA(xa::Arguments),
|
||||
|
@ -37,7 +37,7 @@ impl SubCommands {
|
|||
SubCommands::Nothing => false,
|
||||
SubCommands::SimpleTIM(_) => false,
|
||||
SubCommands::VAG(_) => false,
|
||||
SubCommands::MyXA => false,
|
||||
SubCommands::MyXA(_) => false,
|
||||
|
||||
SubCommands::XA(_) => true
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ fn run_internal_conversion(cmd: CommandLine) -> Result<(), Error> {
|
|||
SubCommands::Nothing => nothing::copy(&mut input, dst_buffer),
|
||||
SubCommands::SimpleTIM(args) => reduced_tim::convert(args, input, dst_buffer),
|
||||
SubCommands::VAG(args) => audio::vag::convert(args, &cmd.output_file, input, dst_buffer),
|
||||
SubCommands::MyXA => audio::my_xa::convert(input, dst_buffer),
|
||||
SubCommands::MyXA(args) => audio::my_xa::convert(args, input, dst_buffer),
|
||||
_ => Err(Error::from_str("External functions can not be called for internal conversion"))
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue