Skip to main content

rescale_core/
normalize.rs

1//! Modul normalisasi audio berdasarkan Peak dan RMS.
2
3use crate::gain::Gain;
4
5pub struct Normalizer;
6
7impl Normalizer {
8    /// Mencari nilai absolut amplitude terbesar dalam buffer.
9    #[inline]
10    pub fn find_peak(buffer: &[f32]) -> f32 {
11        buffer
12            .iter()
13            .map(|&x| x.abs())
14            .fold(0.0_f32, |acc, x| acc.max(x))
15    }
16
17    /// Menghitung Root Mean Square (RMS) dari buffer.
18    #[inline]
19    pub fn calculate_rms(buffer: &[f32]) -> f32 {
20        if buffer.is_empty() {
21            return 0.0;
22        }
23        let sum_squares: f32 = buffer.iter().map(|&x| x * x).sum();
24        (sum_squares / buffer.len() as f32).sqrt()
25    }
26
27    /// Menskalakan buffer agar amplitude peak mencapai `target_peak`.
28    /// Mengembalikan rasio gain yang diterapkan.
29    pub fn normalize_to_peak(buffer: &mut [f32], target_peak: f32) -> f32 {
30        let current_peak = Self::find_peak(buffer);
31        if current_peak > 1e-6 {
32            let gain = target_peak / current_peak;
33            for sample in buffer.iter_mut() {
34                *sample *= gain;
35            }
36            gain
37        } else {
38            1.0
39        }
40    }
41
42    /// Menormalkan seluruh channel dengan gain yang sama agar balance stereo tetap terjaga.
43    pub fn normalize_channels_to_peak(channels: &mut [Vec<f32>], target_peak: f32) -> f32 {
44        let current_peak = channels
45            .iter()
46            .map(|channel| Self::find_peak(channel))
47            .fold(0.0_f32, f32::max);
48
49        if current_peak <= 1e-6 {
50            return 1.0;
51        }
52
53        let gain = target_peak / current_peak;
54        for channel in channels {
55            Gain::apply_linear(channel, gain);
56        }
57        gain
58    }
59}