fundsp/
dynamics.rs

1//! Audio dynamics related components.
2
3use super::audionode::*;
4use super::buffer::*;
5use super::follow::*;
6use super::math::*;
7use super::shared::*;
8use super::signal::*;
9use super::*;
10use core::sync::atomic::AtomicU32;
11use numeric_array::typenum::*;
12extern crate alloc;
13use alloc::sync::Arc;
14use alloc::vec::Vec;
15
16/// Binary operation for the monoidal reducer.
17pub trait Monoidal<T>: Clone {
18    fn binop(&self, x: T, y: T) -> T;
19}
20
21#[derive(Default, Clone)]
22pub struct Amplitude<T: Num> {
23    _marker: core::marker::PhantomData<T>,
24}
25
26impl<T: Num> Amplitude<T> {
27    pub fn new() -> Self {
28        Amplitude::default()
29    }
30}
31
32impl<T: Num> Monoidal<T> for Amplitude<T> {
33    #[inline]
34    fn binop(&self, x: T, y: T) -> T {
35        max(abs(x), abs(y))
36    }
37}
38
39#[derive(Default, Clone)]
40pub struct Maximum<T: Num> {
41    _marker: core::marker::PhantomData<T>,
42}
43
44impl<T: Num> Maximum<T> {
45    pub fn new() -> Self {
46        Maximum::default()
47    }
48}
49
50impl<T: Num> Monoidal<T> for Maximum<T> {
51    #[inline]
52    fn binop(&self, x: T, y: T) -> T {
53        max(x, y)
54    }
55}
56
57/// Hierarchic reducer for a monoid.
58#[derive(Clone)]
59pub struct ReduceBuffer<T, B>
60where
61    T: Num,
62    B: Monoidal<T>,
63{
64    // First item is unused for convenience. Buffer length is rounded up to an even number.
65    buffer: Vec<T>,
66    length: usize,
67    leaf_offset: usize,
68    binop: B,
69}
70
71impl<T, B> ReduceBuffer<T, B>
72where
73    T: Num,
74    B: Monoidal<T>,
75{
76    #[inline]
77    fn get_index(&self, i: usize) -> usize {
78        self.leaf_offset + i
79    }
80
81    // Assumption: 0 is the zero element.
82    pub fn new(length: usize, binop: B) -> Self {
83        let leaf_offset = length.next_power_of_two();
84        let mut buffer = Self {
85            buffer: Vec::new(),
86            length,
87            leaf_offset,
88            binop,
89        };
90        buffer
91            .buffer
92            .resize(leaf_offset + length + (length & 1), T::zero());
93        buffer
94    }
95
96    #[inline]
97    pub fn length(&self) -> usize {
98        self.length
99    }
100
101    #[inline]
102    pub fn total(&self) -> T {
103        self.buffer[1]
104    }
105
106    pub fn set(&mut self, index: usize, value: T) {
107        let mut i = self.get_index(index);
108        self.buffer[i] = value;
109        while i > 1 {
110            let reduced = self.binop.binop(self.buffer[i], self.buffer[i ^ 1]);
111            i >>= 1;
112            self.buffer[i] = reduced;
113        }
114    }
115
116    pub fn clear(&mut self) {
117        for i in 0..self.buffer.len() {
118            self.buffer[i] = T::zero();
119        }
120    }
121}
122
123/// Look-ahead limiter.
124#[derive(Clone)]
125pub struct Limiter<N>
126where
127    N: Size<f32>,
128{
129    lookahead: f64,
130    #[allow(dead_code)]
131    release: f64,
132    sample_rate: f64,
133    reducer: ReduceBuffer<f32, Maximum<f32>>,
134    follower: AFollow<f32>,
135    buffer: Vec<Frame<f32, N>>,
136    index: usize,
137}
138
139impl<N> Limiter<N>
140where
141    N: Size<f32>,
142{
143    #[inline]
144    fn advance(&mut self) {
145        self.index += 1;
146        if self.index >= self.reducer.length() {
147            self.index = 0;
148        }
149    }
150
151    fn buffer_length(sample_rate: f64, lookahead: f64) -> usize {
152        max(1, round(sample_rate * lookahead) as usize)
153    }
154
155    fn new_buffer(sample_rate: f64, lookahead: f64) -> ReduceBuffer<f32, Maximum<f32>> {
156        ReduceBuffer::new(Self::buffer_length(sample_rate, lookahead), Maximum::new())
157    }
158
159    pub fn new(sample_rate: f64, attack_time: f32, release_time: f32) -> Self {
160        let mut follower = AFollow::new(attack_time * 0.4, release_time * 0.4);
161        follower.set_sample_rate(sample_rate);
162        Limiter {
163            lookahead: attack_time as f64,
164            release: release_time as f64,
165            sample_rate,
166            follower,
167            buffer: Vec::new(),
168            reducer: Self::new_buffer(sample_rate, attack_time.to_f64()),
169            index: 0,
170        }
171    }
172}
173
174impl<N> AudioNode for Limiter<N>
175where
176    N: Size<f32>,
177{
178    const ID: u64 = 25;
179    type Inputs = N;
180    type Outputs = N;
181
182    fn reset(&mut self) {
183        self.set_sample_rate(self.sample_rate);
184    }
185
186    fn set_sample_rate(&mut self, sample_rate: f64) {
187        self.index = 0;
188        self.sample_rate = sample_rate;
189        let length = Self::buffer_length(sample_rate, self.lookahead);
190        if length != self.reducer.length {
191            self.reducer = Self::new_buffer(sample_rate, self.lookahead);
192        }
193        self.follower.set_sample_rate(sample_rate);
194        self.reducer.clear();
195        self.buffer.clear();
196    }
197
198    #[inline]
199    fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
200        let amplitude = input.iter().fold(0.0, |amp, &x| max(amp, abs(x)));
201        self.reducer.set(self.index, amplitude);
202        if self.buffer.len() < self.reducer.length() {
203            // We are filling up the initial buffer.
204            self.buffer.push(input.clone());
205            if self.buffer.len() == self.reducer.length() {
206                // When the buffer is full, start following from its total peak.
207                self.follower.set_value(self.reducer.total());
208            }
209            self.advance();
210            Frame::default()
211        } else {
212            let output = self.buffer[self.index].clone();
213            self.buffer[self.index] = input.clone();
214            // Leave some headroom.
215            self.follower
216                .filter_mono(max(1.0, self.reducer.total() * 1.10));
217            self.advance();
218            let limit = self.follower.value();
219            output * Frame::splat(1.0 / limit)
220        }
221    }
222
223    fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
224        let mut output = SignalFrame::new(self.outputs());
225        for i in 0..N::USIZE {
226            // We pretend that the limiter does not alter the frequency response.
227            output.set(i, input.at(i).delay(self.reducer.length() as f64));
228        }
229        output
230    }
231
232    fn allocate(&mut self) {
233        if self.buffer.capacity() < self.reducer.length() {
234            self.buffer
235                .reserve(self.reducer.length() - self.buffer.capacity());
236        }
237    }
238}
239
240/// Transient filter. Multiply the signal with a fade-in curve.
241/// After fade-in, pass signal through.
242/// - Input 0: input signal
243/// - Output 0: filtered signal
244#[derive(Default, Clone)]
245pub struct Declick<F: Real> {
246    t: F,
247    duration: F,
248    sample_duration: F,
249    sample_rate: f64,
250}
251
252impl<F: Real> Declick<F> {
253    pub fn new(duration: F) -> Self {
254        let mut node = Self {
255            duration,
256            ..Default::default()
257        };
258        node.set_sample_rate(DEFAULT_SR);
259        node
260    }
261}
262
263impl<F: Real> AudioNode for Declick<F> {
264    const ID: u64 = 23;
265    type Inputs = U1;
266    type Outputs = U1;
267
268    fn reset(&mut self) {
269        self.t = F::zero();
270    }
271
272    fn set_sample_rate(&mut self, sample_rate: f64) {
273        self.sample_rate = sample_rate;
274        self.sample_duration = F::from_f64(1.0 / sample_rate);
275    }
276
277    #[inline]
278    fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
279        if self.t < self.duration {
280            let phase = delerp(F::zero(), self.duration, self.t);
281            let value = smooth5(phase);
282            self.t += self.sample_duration;
283            [input[0] * value.to_f32()].into()
284        } else {
285            [input[0]].into()
286        }
287    }
288
289    fn process(&mut self, size: usize, input: &BufferRef, output: &mut BufferMut) {
290        output.channel_mut(0)[..simd_items(size)]
291            .clone_from_slice(&input.channel(0)[..simd_items(size)]);
292        if self.t < self.duration {
293            let mut phase = delerp(F::zero(), self.duration, self.t);
294            let phase_d = self.sample_duration / self.duration;
295            let end_time = self.t + F::new(size as i64) * self.sample_duration;
296            let end_index = if self.duration < end_time {
297                ceil((self.duration - self.t) / self.sample_duration).to_i64() as usize
298            } else {
299                size
300            };
301            for x in output.channel_f32_mut(0)[0..end_index].iter_mut() {
302                *x *= smooth5(phase).to_f32();
303                phase += phase_d;
304            }
305            self.t = end_time;
306        }
307    }
308
309    fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
310        // We pretend that the declicker does not alter the frequency response.
311        input.clone()
312    }
313}
314
315/// Metering modes.
316#[derive(Copy, Clone)]
317pub enum Meter {
318    /// Latest value.
319    Sample,
320    /// Peak meter with smoothing timescale in seconds.
321    /// Smoothing timescale is the time it takes for level estimation to move halfway to a new level.
322    Peak(f64),
323    /// RMS meter with smoothing timescale in seconds.
324    /// Smoothing timescale is the time it takes for level estimation to move halfway to a new level.
325    Rms(f64),
326}
327
328impl Meter {
329    /// Whether the meter mode depends only on the latest sample.
330    pub fn latest_only(&self) -> bool {
331        matches!(self, Meter::Sample)
332    }
333}
334
335#[derive(Clone)]
336pub struct MeterState {
337    /// Per-sample smoothing calculated from smoothing timescale.
338    smoothing: f32,
339    /// Current meter level.
340    state: f32,
341}
342
343impl MeterState {
344    /// Create a new MeterState for the given metering mode.
345    pub fn new(meter: Meter) -> Self {
346        let mut state = Self {
347            smoothing: 0.0,
348            state: 0.0,
349        };
350        state.set_sample_rate(meter, DEFAULT_SR);
351        state
352    }
353
354    /// Reset meter state.
355    pub fn reset(&mut self, _meter: Meter) {
356        self.state = 0.0;
357    }
358
359    /// Set meter sample rate.
360    pub fn set_sample_rate(&mut self, meter: Meter, sample_rate: f64) {
361        let timescale = match meter {
362            Meter::Sample => {
363                return;
364            }
365            Meter::Peak(timescale) => timescale,
366            Meter::Rms(timescale) => timescale,
367        };
368        self.smoothing = (pow(0.5f64, 1.0 / (timescale * sample_rate))).to_f32();
369    }
370
371    /// Process an input sample.
372    #[inline]
373    pub fn tick(&mut self, meter: Meter, value: f32) {
374        match meter {
375            Meter::Sample => self.state = value,
376            Meter::Peak(_) => self.state = max(self.state * self.smoothing, abs(value)),
377            Meter::Rms(_) => {
378                self.state = self.state * self.smoothing + squared(value) * (1.0 - self.smoothing)
379            }
380        }
381    }
382
383    /// Current meter level.
384    #[inline]
385    pub fn level(&self, meter: Meter) -> f32 {
386        match meter {
387            Meter::Sample => self.state,
388            Meter::Peak(_) => self.state,
389            Meter::Rms(_) => sqrt(self.state),
390        }
391    }
392}
393
394/// Meters the input and outputs a summary according to the chosen metering mode.
395/// - Input 0: input signal
396/// - Output 0: input summary
397#[derive(Clone)]
398pub struct MeterNode {
399    meter: Meter,
400    state: MeterState,
401}
402
403impl MeterNode {
404    /// Create a new metering node.
405    pub fn new(meter: Meter) -> Self {
406        Self {
407            meter,
408            state: MeterState::new(meter),
409        }
410    }
411}
412
413impl AudioNode for MeterNode {
414    const ID: u64 = 61;
415    type Inputs = U1;
416    type Outputs = U1;
417
418    fn reset(&mut self) {
419        self.state.reset(self.meter);
420    }
421
422    fn set_sample_rate(&mut self, sample_rate: f64) {
423        self.state.set_sample_rate(self.meter, sample_rate);
424    }
425
426    #[inline]
427    fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
428        self.state.tick(self.meter, input[0]);
429        [convert(self.state.level(self.meter))].into()
430    }
431
432    fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
433        let mut output = SignalFrame::new(self.outputs());
434        output.set(0, input.at(0).distort(0.0));
435        output
436    }
437}
438
439/// Pass through input unchanged.
440/// Summary of the input signal is placed in a shared variable.
441pub struct Monitor {
442    meter: Meter,
443    state: MeterState,
444    shared: Arc<AtomicU32>,
445}
446
447impl Clone for Monitor {
448    fn clone(&self) -> Self {
449        Self {
450            meter: self.meter,
451            state: self.state.clone(),
452            shared: Arc::clone(&self.shared),
453        }
454    }
455}
456
457impl Monitor {
458    /// Create a new monitor node.
459    pub fn new(shared: &Shared, meter: Meter) -> Self {
460        Self {
461            meter,
462            state: MeterState::new(meter),
463            shared: Arc::clone(shared.get_shared()),
464        }
465    }
466}
467
468impl AudioNode for Monitor {
469    const ID: u64 = 56;
470    type Inputs = U1;
471    type Outputs = U1;
472
473    fn reset(&mut self) {
474        self.state.reset(self.meter);
475    }
476
477    fn set_sample_rate(&mut self, sample_rate: f64) {
478        self.state.set_sample_rate(self.meter, sample_rate);
479    }
480
481    #[inline]
482    fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
483        self.state.tick(self.meter, input[0]);
484        f32::store(&self.shared, self.state.level(self.meter));
485        *input
486    }
487
488    fn process(&mut self, size: usize, input: &BufferRef, output: &mut BufferMut) {
489        if size == 0 {
490            return;
491        }
492        if self.meter.latest_only() {
493            self.state.tick(self.meter, input.at_f32(0, size - 1));
494        } else {
495            for i in 0..size {
496                self.state.tick(self.meter, input.at_f32(0, i));
497            }
498        }
499        // For efficiency, store the value only once per block.
500        f32::store(&self.shared, self.state.level(self.meter));
501        output.channel_mut(0)[..simd_items(size)]
502            .clone_from_slice(&input.channel(0)[..simd_items(size)]);
503    }
504
505    fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
506        input.clone()
507    }
508}