| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
pub fn apply_gain(samples: &mut [f32], db: f64) { |
| 5 |
if samples.is_empty() || db == 0.0 || !db.is_finite() { |
| 6 |
return; |
| 7 |
} |
| 8 |
|
| 9 |
let scale = 10.0_f64.powf(db / 20.0) as f32; |
| 10 |
for sample in samples.iter_mut() { |
| 11 |
*sample = (*sample * scale).clamp(-1.0, 1.0); |
| 12 |
} |
| 13 |
} |
| 14 |
|
| 15 |
#[cfg(test)] |
| 16 |
mod tests { |
| 17 |
use super::*; |
| 18 |
|
| 19 |
#[test] |
| 20 |
fn gain_plus_6db() { |
| 21 |
let mut samples = vec![0.25, -0.25, 0.1]; |
| 22 |
apply_gain(&mut samples, 6.0); |
| 23 |
|
| 24 |
let scale = 10.0_f64.powf(6.0 / 20.0) as f32; |
| 25 |
assert!((samples[0] - 0.25 * scale).abs() < 0.001); |
| 26 |
assert!((samples[1] - (-0.25 * scale)).abs() < 0.001); |
| 27 |
} |
| 28 |
|
| 29 |
#[test] |
| 30 |
fn gain_minus_6db() { |
| 31 |
let mut samples = vec![1.0, -1.0, 0.5]; |
| 32 |
apply_gain(&mut samples, -6.0); |
| 33 |
let scale = 10.0_f64.powf(-6.0 / 20.0) as f32; |
| 34 |
assert!((samples[0] - scale).abs() < 0.001); |
| 35 |
} |
| 36 |
|
| 37 |
#[test] |
| 38 |
fn gain_zero_is_noop() { |
| 39 |
let original = vec![0.5, -0.5, 0.25]; |
| 40 |
let mut samples = original.clone(); |
| 41 |
apply_gain(&mut samples, 0.0); |
| 42 |
assert_eq!(samples, original); |
| 43 |
} |
| 44 |
|
| 45 |
#[test] |
| 46 |
fn gain_clips_to_bounds() { |
| 47 |
let mut samples = vec![0.5, -0.5]; |
| 48 |
apply_gain(&mut samples, 24.0); |
| 49 |
assert_eq!(samples[0], 1.0); |
| 50 |
assert_eq!(samples[1], -1.0); |
| 51 |
} |
| 52 |
|
| 53 |
#[test] |
| 54 |
fn gain_empty() { |
| 55 |
let mut samples: Vec<f32> = vec![]; |
| 56 |
apply_gain(&mut samples, 6.0); |
| 57 |
assert!(samples.is_empty()); |
| 58 |
} |
| 59 |
} |
| 60 |
|