firewheel_core/dsp/
coeff_update.rs

1use crate::{
2    diff::{Diff, Patch},
3    event::ParamData,
4};
5
6/// An exponent representing the rate at which DSP coefficients are
7/// updated when parameters are being smoothed.
8///
9/// Smaller values will produce less "stair-stepping" artifacts,
10/// but will also consume more CPU.
11///
12/// The resulting number of frames (samples in a single channel of audio)
13/// that will elapse between each update is calculated as
14/// `2^coeff_update_mask`.
15///
16/// By default this is set to `5`.
17#[repr(transparent)]
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
20pub struct CoeffUpdateFactor(pub u32);
21
22impl CoeffUpdateFactor {
23    pub fn interval_frames(&self) -> usize {
24        2u32.pow(self.0) as usize
25    }
26
27    pub fn mask(&self) -> CoeffUpdateMask {
28        CoeffUpdateMask((2u32.pow(self.0) - 1) as usize)
29    }
30}
31
32impl Default for CoeffUpdateFactor {
33    fn default() -> Self {
34        Self(5)
35    }
36}
37
38impl From<u32> for CoeffUpdateFactor {
39    fn from(value: u32) -> Self {
40        Self(value)
41    }
42}
43
44impl From<CoeffUpdateFactor> for u32 {
45    fn from(value: CoeffUpdateFactor) -> Self {
46        value.0
47    }
48}
49
50impl Diff for CoeffUpdateFactor {
51    fn diff<E: crate::diff::EventQueue>(
52        &self,
53        baseline: &Self,
54        path: crate::diff::PathBuilder,
55        event_queue: &mut E,
56    ) {
57        if self != baseline {
58            event_queue.push_param(ParamData::U32(self.0), path);
59        }
60    }
61}
62
63impl Patch for CoeffUpdateFactor {
64    type Patch = Self;
65
66    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, crate::diff::PatchError> {
67        match data {
68            ParamData::U32(value) => Ok(Self(*value)),
69            _ => Err(crate::diff::PatchError::InvalidData),
70        }
71    }
72
73    fn apply(&mut self, patch: Self::Patch) {
74        *self = patch;
75    }
76}
77
78/// Used in conjunction with [`CoeffUpdateFactor`].
79#[repr(transparent)]
80#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
81pub struct CoeffUpdateMask(pub usize);
82
83impl Default for CoeffUpdateMask {
84    fn default() -> Self {
85        CoeffUpdateFactor::default().mask()
86    }
87}
88
89impl CoeffUpdateMask {
90    #[inline(always)]
91    pub fn do_update(&self, i: usize) -> bool {
92        i & self.0 == 0
93    }
94}