diff --git a/crates/audio-io/src/peaks.rs b/crates/audio-io/src/peaks.rs index 9553665c..6cd8f321 100644 --- a/crates/audio-io/src/peaks.rs +++ b/crates/audio-io/src/peaks.rs @@ -24,14 +24,14 @@ pub struct Peaks { struct Block { min: f32, max: f32, - squares: f32, + squares: f64, } impl Block { const EMPTY: Block = Block { min: f32::INFINITY, max: f32::NEG_INFINITY, squares: 0.0 }; fn point(s: f32) -> Block { - Block { min: s, max: s, squares: if s.is_finite() { s * s } else { 0.0 } } + Block { min: s, max: s, squares: if s.is_finite() { f64::from(s) * f64::from(s) } else { 0.0 } } } fn of(samples: &[f32]) -> Block { @@ -146,7 +146,7 @@ impl Peaks { .map(|w| { w.map(|(a, b)| { let (s, e) = (a.floor() as usize, (b.ceil() as usize).saturating_add(1).min(self.len).min(samples.len())); - (self.sum(samples, s, e).squares / e.saturating_sub(s).max(1) as f32).sqrt() + (self.sum(samples, s, e).squares / e.saturating_sub(s).max(1) as f64).sqrt() as f32 }) }) .collect() @@ -215,6 +215,13 @@ mod tests { assert!(p.rms_spans(&x, 0.0, 1.0, 0.0, 1)[0].is_some_and(f32::is_finite)); } + #[test] + fn finite_large_samples_keep_finite_rms() { + let samples = vec![1e20_f32; BLOCK]; + let peaks = Peaks::build(&samples); + assert_eq!(peaks.rms_spans(&samples, 0.0, BLOCK as f64, 0.0, 1), vec![Some(1e20)]); + } + #[test] fn rms_spans_match_the_samples() { let x = signal(20_000);