[WIP] Audio codec probe/detection + CLI audio-info + viewer audio panel
Snapshot of local WIP before rebasing onto the movie/voice remote work. - audio.rs: AudioCodec enum, AudioInfo::probe (RIFF/WAVE parse, raw-XMA2 Shannon-entropy heuristic looks_like_raw_xma2), from_wav, riff_data_span. - cli/main.rs: `audio-info` subcommand (cmd_audio_info). - viewer ui.rs/iso_loader.rs: draw_audio_detail panel wiring. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -103,6 +103,21 @@ enum Commands {
|
||||
#[command(subcommand)]
|
||||
cmd: MeshCommands,
|
||||
},
|
||||
|
||||
/// Audio tools (identify WAV/XMA/XMA2 + metadata)
|
||||
Audio {
|
||||
#[command(subcommand)]
|
||||
cmd: AudioCommands,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum AudioCommands {
|
||||
/// Identify an audio file/stream and print its metadata
|
||||
Info {
|
||||
/// Path to a WAV / XMA / raw audio stream
|
||||
file: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
@@ -202,9 +217,41 @@ async fn main() -> Result<()> {
|
||||
PakCommands::List { pak, idxd_only } => cmd_pak_list(&pak, idxd_only),
|
||||
PakCommands::Dump { pak, hash } => cmd_pak_dump(&pak, &hash),
|
||||
},
|
||||
Commands::Audio { cmd } => match cmd {
|
||||
AudioCommands::Info { file } => cmd_audio_info(&file),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ── audio info ───────────────────────────────────────────────────────────────
|
||||
|
||||
fn cmd_audio_info(file: &Path) -> Result<()> {
|
||||
use sylpheed_formats::AudioInfo;
|
||||
let bytes = std::fs::read(file).with_context(|| format!("Cannot read {}", file.display()))?;
|
||||
let info = AudioInfo::probe(&bytes);
|
||||
|
||||
println!("{} {}", "Audio:".green().bold(), file.display());
|
||||
println!(" Codec : {}", info.codec.label().yellow());
|
||||
let opt = |v: Option<String>| v.unwrap_or_else(|| "—".dimmed().to_string());
|
||||
println!(" Channels : {}", opt(info.channels.map(|c| c.to_string())));
|
||||
println!(" Sample rate: {}", opt(info.sample_rate.map(|r| format!("{r} Hz"))));
|
||||
println!(" Bit depth : {}", opt(info.bits_per_sample.map(|b| format!("{b}-bit"))));
|
||||
if let Some(d) = info.duration_secs {
|
||||
println!(" Duration : {d:.2} s");
|
||||
}
|
||||
if let Some(p) = info.xma_packets {
|
||||
println!(" XMA packets: {} (2048 B each)", p.to_string().yellow());
|
||||
}
|
||||
println!(" Size : {} bytes", info.size_bytes.to_string().yellow());
|
||||
if info.codec.needs_decoder() {
|
||||
println!(
|
||||
" {} decode not supported (needs an XMA2 decoder + the sound-bank descriptor)",
|
||||
"note:".dimmed()
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// ── extract ────────────────────────────────────────────────────────────────
|
||||
|
||||
async fn cmd_extract(iso_path: &Path, output_dir: &Path) -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user