1use std::process;
15use std::time::Duration;
16
17use ff_analysis::{WaveformAnalyzer, WaveformSample};
18
19fn fmt_db(db: f32) -> String {
20 if db == f32::NEG_INFINITY {
21 "-inf".to_string()
22 } else {
23 format!("{db:+.1}")
24 }
25}
26
27fn main() {
28 let mut args = std::env::args().skip(1);
29 let mut input = None::<String>;
30 let mut interval_ms = 100u64;
31
32 while let Some(flag) = args.next() {
33 match flag.as_str() {
34 "--input" | "-i" => input = Some(args.next().unwrap_or_default()),
35 "--interval-ms" => {
36 let raw = args.next().unwrap_or_default();
37 interval_ms = raw.parse().unwrap_or_else(|_| {
38 eprintln!("Invalid interval-ms: {raw}");
39 process::exit(1);
40 });
41 }
42 other => {
43 eprintln!("Unknown flag: {other}");
44 process::exit(1);
45 }
46 }
47 }
48
49 let input = input.unwrap_or_else(|| {
50 eprintln!("Usage: waveform --input <audio> [--interval-ms <ms>]");
51 process::exit(1);
52 });
53
54 println!("Analyzing waveform: {input}");
55 println!("Interval: {interval_ms} ms");
56 println!();
57
58 let samples: Vec<WaveformSample> = WaveformAnalyzer::new(&input)
59 .interval(Duration::from_millis(interval_ms))
60 .run()
61 .unwrap_or_else(|e| {
62 eprintln!("Error: {e}");
63 process::exit(1);
64 });
65
66 println!("{} interval(s) analyzed.", samples.len());
67 println!();
68
69 let display_count = samples.len().min(20);
71 println!(
72 "{:<12} {:>10} {:>10}",
73 "Time (s)", "Peak dBFS", "RMS dBFS"
74 );
75 println!("{}", "-".repeat(38));
76 for s in samples.iter().take(display_count) {
77 let secs = s.timestamp.as_secs_f64();
78 println!(
79 "{secs:<12.3} {:>10} {:>10}",
80 fmt_db(s.peak_db),
81 fmt_db(s.rms_db)
82 );
83 }
84 if samples.len() > display_count {
85 println!(" … ({} more intervals)", samples.len() - display_count);
86 }
87}