xsynth_core/effects/
limiter.rs1use std::marker::PhantomData;
2
3struct SingleChannelLimiter {
4 loudness: f32,
5 attack: f32,
6 falloff: f32,
7 strength: f32,
8 min_thresh: f32,
9}
10
11impl SingleChannelLimiter {
12 fn new() -> SingleChannelLimiter {
13 SingleChannelLimiter {
14 loudness: 1.0,
15 attack: 100.0,
16 falloff: 16000.0,
17 strength: 1.0,
18 min_thresh: 1.0,
19 }
20 }
21
22 fn limit(&mut self, val: f32) -> f32 {
23 let abs = val.abs();
24 if self.loudness > abs {
25 self.loudness = (self.loudness * self.falloff + abs) / (self.falloff + 1.0);
26 } else {
27 self.loudness = (self.loudness * self.attack + abs) / (self.attack + 1.0);
28 }
29
30 if self.loudness < self.min_thresh {
31 self.loudness = self.min_thresh;
32 }
33
34 let val = val / (self.loudness * self.strength + 2.0 * (1.0 - self.strength)) / 2.0;
35
36 val
37 }
38}
39
40pub struct VolumeLimiter {
44 channels: Vec<SingleChannelLimiter>,
45 channel_count: usize,
46}
47
48pub struct VolumeLimiterIter<'a, 'b, T: 'b + Iterator<Item = f32>> {
49 limiter: &'a mut VolumeLimiter,
50 samples: T,
51 pos: usize,
52 _b: PhantomData<&'b T>,
53}
54
55impl VolumeLimiter {
56 pub fn new(channel_count: u16) -> VolumeLimiter {
58 let mut limiters = Vec::new();
59 for _ in 0..channel_count {
60 limiters.push(SingleChannelLimiter::new());
61 }
62 VolumeLimiter {
63 channels: limiters,
64 channel_count: channel_count as usize,
65 }
66 }
67
68 pub fn limit(&mut self, sample: &mut [f32]) {
70 for (i, s) in sample.iter_mut().enumerate() {
71 *s = self.channels[i % self.channel_count].limit(*s);
72 }
73 }
74
75 pub fn limit_iter<'a, 'b, T: 'b + Iterator<Item = f32>>(
76 &'a mut self,
77 samples: T,
78 ) -> VolumeLimiterIter<'a, 'b, T> {
79 impl<'b, T: 'b + Iterator<Item = f32>> Iterator for VolumeLimiterIter<'_, 'b, T> {
80 type Item = f32;
81
82 fn next(&mut self) -> Option<Self::Item> {
83 let next = self.samples.next();
84 if let Some(next) = next {
85 let val =
86 self.limiter.channels[self.pos % self.limiter.channel_count].limit(next);
87 self.pos += 1;
88 Some(val)
89 } else {
90 None
91 }
92 }
93 }
94
95 VolumeLimiterIter::<'a, 'b, T> {
96 _b: PhantomData,
97 limiter: self,
98 samples,
99 pos: 0,
100 }
101 }
102}