Skip to main content

rescale_core/
safety.rs

1//! Sanitasi sinyal audio: guard NaN/Inf dan flush nilai denormal.
2
3/// Nilai absolut di bawah ambang ini dianggap denormal dan dibulatkan ke nol.
4pub const DENORMAL_THRESHOLD: f32 = 1e-30;
5
6/// Mensterilkan satu sample: non-finite menjadi 0.0, denormal menjadi 0.0.
7///
8/// Nilai NaN/Inf dapat menyebar ke seluruh buffer dengan cepat (umpan balik
9/// filter/kompresor), dan denormal membuat operasi floating-point melambat
10/// drastis di banyak CPU. Sanitasi di boundary engine mencegah keduanya.
11#[inline(always)]
12pub fn sanitize_sample(sample: f32) -> f32 {
13    if !sample.is_finite() {
14        return 0.0;
15    }
16    if sample.abs() < DENORMAL_THRESHOLD {
17        return 0.0;
18    }
19    sample
20}
21
22/// Mensterilkan seluruh sample dalam buffer in-place.
23pub fn sanitize_buffer(buffer: &mut [f32]) {
24    for sample in buffer.iter_mut() {
25        *sample = sanitize_sample(*sample);
26    }
27}
28
29/// Mensterilkan seluruh channel pada sebuah audio block.
30pub fn sanitize_block(block: &mut crate::engine::AudioBlock<'_>) {
31    for channel_index in 0..block.channels() {
32        if let Some(channel) = block.channel_mut(channel_index) {
33            sanitize_buffer(channel);
34        }
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn non_finite_values_become_silence() {
44        assert_eq!(sanitize_sample(f32::NAN), 0.0);
45        assert_eq!(sanitize_sample(f32::INFINITY), 0.0);
46        assert_eq!(sanitize_sample(f32::NEG_INFINITY), 0.0);
47    }
48
49    #[test]
50    fn denormals_and_finite_values() {
51        assert_eq!(sanitize_sample(1e-32), 0.0);
52        assert!((sanitize_sample(0.5) - 0.5).abs() < 1e-6);
53        assert!((sanitize_sample(-0.25) + 0.25).abs() < 1e-6);
54    }
55
56    #[test]
57    fn buffer_is_sanitized_in_place() {
58        let mut buffer = [f32::NAN, 0.5, f32::INFINITY, 1e-35];
59        sanitize_buffer(&mut buffer);
60        assert_eq!(buffer, [0.0, 0.5, 0.0, 0.0]);
61    }
62}