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))]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub struct CoeffUpdateFactor(pub u32);
22
23impl CoeffUpdateFactor {
24    pub const DEFAULT: Self = Self(5);
25
26    pub fn interval_frames(&self) -> usize {
27        2u32.pow(self.0) as usize
28    }
29
30    pub fn mask(&self) -> CoeffUpdateMask {
31        CoeffUpdateMask((2u32.pow(self.0) - 1) as usize)
32    }
33}
34
35impl Default for CoeffUpdateFactor {
36    fn default() -> Self {
37        Self::DEFAULT
38    }
39}
40
41impl From<u32> for CoeffUpdateFactor {
42    fn from(value: u32) -> Self {
43        Self(value)
44    }
45}
46
47impl From<CoeffUpdateFactor> for u32 {
48    fn from(value: CoeffUpdateFactor) -> Self {
49        value.0
50    }
51}
52
53impl Diff for CoeffUpdateFactor {
54    fn diff<E: crate::diff::EventQueue>(
55        &self,
56        baseline: &Self,
57        path: crate::diff::PathBuilder,
58        event_queue: &mut E,
59    ) {
60        if self != baseline {
61            event_queue.push_param(ParamData::U32(self.0), path);
62        }
63    }
64}
65
66impl Patch for CoeffUpdateFactor {
67    type Patch = Self;
68
69    fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, crate::diff::PatchError> {
70        match data {
71            ParamData::U32(value) => Ok(Self(*value)),
72            _ => Err(crate::diff::PatchError::InvalidData),
73        }
74    }
75
76    fn apply(&mut self, patch: Self::Patch) {
77        *self = patch;
78    }
79}
80
81/// Used in conjunction with [`CoeffUpdateFactor`].
82#[repr(transparent)]
83#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
84pub struct CoeffUpdateMask(pub usize);
85
86impl Default for CoeffUpdateMask {
87    fn default() -> Self {
88        CoeffUpdateFactor::default().mask()
89    }
90}
91
92impl CoeffUpdateMask {
93    #[inline(always)]
94    pub fn do_update(&self, i: usize) -> bool {
95        i & self.0 == 0
96    }
97}