Convert wav files to .vag

This commit is contained in:
jaby 2024-08-04 17:41:20 -05:00
parent 746590eef3
commit 0dc1f522c5
8 changed files with 93 additions and 86 deletions

View File

@ -12,7 +12,7 @@ CLUT_4_COLOR_TRANS_FLAGS = simple-tim clut4 --color-trans
## Music tracks
INPUT += $(OUTPUT_DIR)/Evacuation_cdda.xa
INPUT += $(OUTPUT_DIR)/fox.xa
INPUT += $(OUTPUT_DIR)/apple.adpcm
INPUT += $(OUTPUT_DIR)/apple.vag
## Images
INPUT += $(OUTPUT_DIR)/TexturePage.img
@ -37,9 +37,9 @@ $(OUTPUT_DIR)/fox.xa: audio/temp/fox.wav
@mkdir -p $(OUTPUT_DIR)
jaby_engine_fconv $< -o $@ xa
$(OUTPUT_DIR)/%.adpcm: audio/temp/%.wav
$(OUTPUT_DIR)/%.vag: audio/temp/%.wav
@mkdir -p $(OUTPUT_DIR)
jaby_engine_fconv $< -o $@ adpcm
jaby_engine_fconv $< -o $@ vag
$(OUTPUT_DIR)/%.xa: audio/%.wav
@mkdir -p $(OUTPUT_DIR)

View File

@ -45,7 +45,7 @@
</InterleavedFile>
</Directory>
<Directory name = "SFX" hidden = "true">
<File name = "APPLE.ADP" lz4 = "none">../assets/bin/apple.adpcm</File>
<File name = "APPLE.VAG" lz4 = "none">../assets/bin/apple.vag</File>
</Directory>
</Filesystem>
<AudioTrack align = "true">../assets/audio/temp/breaking.wav</AudioTrack>

View File

@ -1,6 +1,6 @@
[package]
name = "jaby_engine_fconv"
version = "0.1.6"
version = "0.2.0"
edition = "2021"
[profile.release]
@ -8,7 +8,6 @@ panic = "abort"
[dependencies]
clap = {version = "4.4.11", features = ["derive"]}
hound = "3.5.1"
image = "0.24.7"
paste = "1.0.14"
png = "0.17.10"

View File

@ -1,41 +0,0 @@
use clap::{Args, ValueEnum};
use hound::Sample;
use image::{DynamicImage, io::Reader as ImageReader};
use std::io::{Cursor, Write};
use tool_helper::{print_warning, Error, Input};
#[derive(Args)]
pub struct Arguments {
}
pub fn convert(input: Input, output: &mut dyn Write) -> Result<(), Error> {
let mut audio_io = hound::WavReader::new(input)?;
let header = audio_io.spec();
if header.sample_format != hound::SampleFormat::Int ||header.bits_per_sample != 16 {
return Err(Error::from_str("Only 16bit integer samples are supported"));
}
if header.channels > 1 {
print_warning("Found more than one audio channel. First channel will be encoded.".to_owned());
}
let active_channel = 1;
let mut sample_count = 0;
for sample in audio_io.samples::<i16>() {
match sample {
Ok(sample) => {
sample_count += 1;
if sample_count%active_channel == 0 {
output.write(&sample.to_le_bytes())?;
}
}
Err(error) => {
return Err(Error::from_text(format!("Failed iterating over samples: {}", error)));
}
}
}
Ok(())
}

View File

@ -1,2 +1,43 @@
pub mod adpcm;
pub mod xa;
pub mod vag;
use std::{env, path::PathBuf, process::Command};
use tool_helper::Error;
fn run_psxavenc<I, S>(input: PathBuf, output: PathBuf, args: I) -> Result<(), Error>
where
I: IntoIterator<Item = S>,
S: AsRef<std::ffi::OsStr>, {
let psxavenc = get_psxavenc_path()?;
let result = Command::new(psxavenc).args(args).arg(input.to_string_lossy().as_ref()).arg(output.to_string_lossy().as_ref()).output()?;
let stderr = tool_helper::vec_helper::to_string(result.stderr)?;
let stdout = tool_helper::vec_helper::to_string(result.stdout)?;
if !result.status.success() {
return Err(Error::from_text(format!("psxavenc returned: {}. {}", result.status, stderr)));
}
if !stdout.is_empty() {
println!("{}", stdout);
}
Ok(())
}
fn get_psxavenc_path() -> Result<PathBuf, Error> {
let tool_path = {
let mut my_path = env::current_exe()?;
my_path.pop();
my_path.push("extern");
my_path.push("psxavenc");
my_path
};
if !tool_path.exists() {
return Err(Error::from_str("Could not locate psxavenc. Make sure it is installed under \"<Jaby Engine>/bin/extern\""));
}
Ok(tool_path)
}

View File

@ -0,0 +1,22 @@
use clap::Args;
use std::path::PathBuf;
use tool_helper::Error;
#[derive(Args)]
pub struct Arguments {
frequency: Option<u32>
}
pub fn convert(args: Arguments, input: PathBuf, output: PathBuf) -> Result<(), Error> {
let mut cmd_args = vec!["-t", "vag"];
let frequency_str;
if let Some(frequency) = args.frequency {
frequency_str = frequency.to_string().to_owned();
cmd_args.push("-f");
cmd_args.push(frequency_str.as_ref());
}
super::run_psxavenc(input, output, cmd_args)
}

View File

@ -1,5 +1,5 @@
use clap::{Args, ValueEnum};
use std::{env, path::PathBuf, process::Command, str};
use std::{path::PathBuf, str};
use tool_helper::Error;
#[derive(Args)]
@ -43,39 +43,13 @@ impl Sample {
pub fn convert(args: Arguments, input: PathBuf, output: PathBuf) -> Result<(), Error> {
let quality = args.quality;
let sample = args.sample;
let tool_path = {
let mut my_path = env::current_exe()?;
my_path.pop();
my_path.push("extern");
my_path.push("psxavenc");
my_path
};
if !tool_path.exists() {
return Err(Error::from_str("Could not locate psxavenc. Make sure it is installed under \"<Jaby Engine>/bin/extern\""));
}
let result = Command::new(tool_path).args([
super::run_psxavenc(input, output, [
"-t", "xacd",
"-f", quality.get_frequency().to_string().as_ref(),
"-b", "4",
"-c", sample.get_channel().to_string().as_ref(),
"-F", "0",
"-C", "0",
input.to_string_lossy().as_ref(), output.to_string_lossy().as_ref()
]) .output()?;
let stderr = tool_helper::vec_helper::to_string(result.stderr)?;
let stdout = tool_helper::vec_helper::to_string(result.stdout)?;
if !result.status.success() {
return Err(Error::from_text(format!("psxavenc returned: {}. {}", result.status, stderr)));
}
if !stdout.is_empty() {
println!("{}", stdout);
}
Ok(())
])
}

View File

@ -24,10 +24,22 @@ enum SubCommands {
// === Internal Commands ===
Nothing,
SimpleTIM(reduced_tim::Arguments),
ADPCM,
// === External Commands ===
XA(xa::Arguments)
VAG(vag::Arguments),
XA(xa::Arguments),
}
impl SubCommands {
pub fn is_external_command(&self) -> bool {
match self {
SubCommands::Nothing => false,
SubCommands::SimpleTIM(_) => false,
SubCommands::VAG(_) => true,
SubCommands::XA(_) => true
}
}
}
fn run_internal_conversion(cmd: CommandLine) -> Result<(), Error> {
@ -48,8 +60,7 @@ fn run_internal_conversion(cmd: CommandLine) -> Result<(), Error> {
match cmd.sub_command {
SubCommands::Nothing => nothing::copy(&mut input, dst_buffer),
SubCommands::SimpleTIM(args) => reduced_tim::convert(args, input, dst_buffer),
SubCommands::ADPCM => adpcm::convert(input, dst_buffer),
_ => Err(Error::not_implemented("External functions can not be called for internal conversion"))
_ => Err(Error::from_str("External functions can not be called for internal conversion"))
}
};
@ -79,13 +90,14 @@ fn run_external_conversion(cmd: CommandLine) -> Result<(), Error> {
let output_file = cmd.output_file.ok_or(Error::from_str("Output has to be a file"))?;
match cmd.sub_command {
SubCommands::VAG(args) => vag::convert(args, input_file, output_file),
SubCommands::XA(args) => xa::convert(args, input_file, output_file),
_ => Err(Error::not_implemented("Internal functions can not be called for external conversion"))
_ => Err(Error::from_str("Internal functions can not be called for external conversion"))
}
}
fn run_main(cmd: CommandLine) -> Result<(), Error> {
if matches!(cmd.sub_command, SubCommands::XA(_)) {
if cmd.sub_command.is_external_command() {
run_external_conversion(cmd)
}