1use ebur128::EbuR128;
2use eyre::{bail, Result};
3
4pub fn audio_resample(
5 data: &[f32],
6 sample_rate0: u32,
7 sample_rate: u32,
8 channels: u16,
9) -> Vec<f32> {
10 use samplerate::{convert, ConverterType};
11 convert(
12 sample_rate0 as _,
13 sample_rate as _,
14 channels as _,
15 ConverterType::SincBestQuality,
16 data,
17 )
18 .unwrap_or_default()
19}
20
21pub fn stereo_to_mono(stereo_data: &[f32]) -> Result<Vec<f32>> {
22 if stereo_data.len() % 2 != 0 {
23 bail!("Stereo data length should be even.")
24 }
25
26 let mut mono_data = Vec::with_capacity(stereo_data.len() / 2);
27
28 for chunk in stereo_data.chunks_exact(2) {
29 let average = (chunk[0] + chunk[1]) / 2.0;
30 mono_data.push(average);
31 }
32
33 Ok(mono_data)
34}
35
36pub struct Normalizer {
37 ebur128: EbuR128,
38}
39
40impl Normalizer {
41 pub fn new(channels: u32, sample_rate: u32) -> Self {
42 let ebur128 = ebur128::EbuR128::new(channels, sample_rate, ebur128::Mode::all())
43 .expect("Failed to create ebur128");
44 Self { ebur128 }
45 }
46
47 pub fn normalize_loudness(&mut self, samples: &[f32]) -> Vec<f32> {
49 self.ebur128.add_frames_f32(samples).unwrap();
51 let loudness = self
52 .ebur128
53 .loudness_global()
54 .expect("Failed to get global loudness");
55 let target_loudness = -23.0; let gain = 10f32.powf(((target_loudness - loudness) / 20.0) as f32);
57
58 let normalized_samples: Vec<f32> = samples
60 .iter()
61 .map(|&sample| (sample * gain).clamp(-1.0, 1.0))
62 .collect();
63
64 normalized_samples
65 }
66}