use std::error::Error;
use std::fs;
use std::path::{Path, PathBuf};
use std::time::Instant;
use paracletics_hypercube::compression::{Codec, CompressionError, compress_with, decompress_with};
use paracletics_hypercube::media_samples::{
synth_symbolic_words, synth_wav_musical_light, synth_y4m_musical_light,
};
const MI_B: f64 = 1024.0 * 1024.0;
#[derive(Debug)]
struct RunRow {
codec: Codec,
output_bytes: usize,
ratio: f64,
enc_ms: f64,
dec_ms: f64,
enc_mib_s: f64,
dec_mib_s: f64,
roundtrip_ok: bool,
}
fn main() -> Result<(), Box<dyn Error>> {
let out_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target/harmonic_storage_samples");
fs::create_dir_all(&out_dir)?;
let wav_path = out_dir.join("musical_light_audio.wav");
let y4m_path = out_dir.join("musical_light_video.y4m");
let text_path = out_dir.join("symbolic_words.txt");
let wav_data = synth_wav_musical_light(44_100, 4.0);
let y4m_data = synth_y4m_musical_light(192, 108, 75, 25);
let text_data = synth_symbolic_words(18_000);
fs::write(&wav_path, &wav_data)?;
fs::write(&y4m_path, &y4m_data)?;
fs::write(&text_path, &text_data)?;
println!("Generated sample files:");
println!(" {}", wav_path.display());
println!(" {}", y4m_path.display());
println!(" {}", text_path.display());
println!();
run_suite("audio/wav", &wav_path, &wav_data)?;
run_suite("video/y4m", &y4m_path, &y4m_data)?;
run_suite("symbolic/text", &text_path, &text_data)?;
Ok(())
}
fn run_suite(label: &str, path: &Path, payload: &[u8]) -> Result<(), Box<dyn Error>> {
println!(
"Dataset: {} ({} bytes) [{}]",
label,
payload.len(),
path.display()
);
println!(
"{:14} {:>10} {:>8} {:>10} {:>10} {:>10} {:>10} {:>10}",
"codec", "output", "ratio", "enc_ms", "dec_ms", "enc MiB/s", "dec MiB/s", "ok"
);
for codec in Codec::ALL {
let row = bench_codec(codec, payload)?;
println!(
"{:14} {:>10} {:>8.3} {:>10.3} {:>10.3} {:>10.2} {:>10.2} {:>10}",
row.codec.name(),
row.output_bytes,
row.ratio,
row.enc_ms,
row.dec_ms,
row.enc_mib_s,
row.dec_mib_s,
if row.roundtrip_ok { "yes" } else { "no" }
);
}
println!();
store_chromoharmonic_artifacts(path, payload)?;
Ok(())
}
fn bench_codec(codec: Codec, input: &[u8]) -> Result<RunRow, CompressionError> {
let start_enc = Instant::now();
let encoded = compress_with(codec, input);
let enc = start_enc.elapsed();
let start_dec = Instant::now();
let decoded = decompress_with(codec, &encoded)?;
let dec = start_dec.elapsed();
let input_bytes = input.len();
let output_bytes = encoded.len();
let ratio = if input_bytes == 0 {
1.0
} else {
output_bytes as f64 / input_bytes as f64
};
let enc_secs = enc.as_secs_f64().max(1e-9);
let dec_secs = dec.as_secs_f64().max(1e-9);
let input_mib = input_bytes as f64 / MI_B;
Ok(RunRow {
codec,
output_bytes,
ratio,
enc_ms: enc_secs * 1000.0,
dec_ms: dec_secs * 1000.0,
enc_mib_s: input_mib / enc_secs,
dec_mib_s: input_mib / dec_secs,
roundtrip_ok: decoded == input,
})
}
fn store_chromoharmonic_artifacts(path: &Path, payload: &[u8]) -> Result<(), Box<dyn Error>> {
let encoded = compress_with(Codec::Chromoharmonic, payload);
let decoded = decompress_with(Codec::Chromoharmonic, &encoded)?;
let encoded_path = path.with_extension(format!(
"{}.chroma",
path.extension().and_then(|s| s.to_str()).unwrap_or("bin")
));
let recovered_path = path.with_extension(format!(
"{}.recovered",
path.extension().and_then(|s| s.to_str()).unwrap_or("bin")
));
fs::write(&encoded_path, &encoded)?;
fs::write(&recovered_path, &decoded)?;
println!("Stored harmonic artifacts:");
println!(" encoded: {}", encoded_path.display());
println!(" recovered: {}", recovered_path.display());
println!(
" byte-exact roundtrip: {}",
if decoded == payload { "yes" } else { "no" }
);
println!();
Ok(())
}