use crate::error::Result;
use crate::metrics::{hiss_db, sharpness, tail_db, true_peak_dbtp};
use crate::wav::WavF64;
use super::pyfmt::{np_round, py_round};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct RawMeasures {
pub sharp: f64,
pub hiss: f64,
pub tail: f64,
pub tp: f64,
}
impl RawMeasures {
pub fn of(wav: &WavF64) -> Result<Self> {
let m = wav.mono();
let rate = wav.sample_rate;
Ok(Self {
sharp: sharpness(&m, rate)?,
hiss: hiss_db(&m, rate)?,
tail: tail_db(&m, rate)?,
tp: true_peak_dbtp(&wav.channel_vecs())?,
})
}
pub fn rounded(&self) -> Self {
Self {
sharp: py_round(self.sharp, 2),
hiss: np_round(self.hiss, 1),
tail: np_round(self.tail, 1),
tp: np_round(self.tp, 1),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_tone_measures_in_range() {
let rate = 48_000u32;
let samples: Vec<f64> = (0..rate as usize)
.flat_map(|i| {
let v = 0.5 * (2.0 * std::f64::consts::PI * 440.0 * i as f64 / 48_000.0).sin();
[v, v]
})
.collect();
let wav = WavF64 {
samples,
sample_rate: rate,
channels: 2,
};
let r = RawMeasures::of(&wav).expect("measures").rounded();
assert!(r.sharp > 0.3 && r.sharp < 0.6, "{r:?}");
assert!(r.hiss < -60.0, "{r:?}");
assert!(r.tail.abs() < 0.5, "{r:?}");
assert!((r.tp - -6.0).abs() < 0.1, "{r:?}");
}
}