Skip to main content

gled_model/sound/
trigger_params.rs

1//! Settings of a sound trigger: which frequency band it listens to and the
2//! envelope it produces, stored with the curve that uses it.
3
4use serde::{Deserialize, Serialize};
5
6/// Highest frequency of the analysed spectrum, in Hz.
7pub const MAX_FREQ: f32 = 24_000.0;
8/// Number of frequency bins of the analysed spectrum.
9pub const FREQ_BINS: usize = 256;
10
11#[derive(Debug, Clone, PartialEq, Copy, Serialize, Deserialize)]
12pub struct SoundTriggerParams {
13    pub(crate) center_bin: usize,
14    pub(crate) bin_radius: usize,
15    pub attack_duration: f32,      // in seconds
16    pub decay_duration: f32,       // in seconds
17    pub(crate) sustain_level: f32, // 0.0 to 1.0
18    pub release_duration: f32,     // in seconds
19    /// Threshold to consider the continuous input "ON"
20    pub sensitivity: f32,
21    pub gate_activation_threshold: f32,
22    pub gate_deactivation_threshold: f32,
23    pub(crate) averaging_samples: usize,
24    pub(crate) echo_samples: usize,
25}
26impl SoundTriggerParams {
27    #[allow(clippy::too_many_arguments)]
28    pub(crate) fn new(
29        f_center: f32,
30        f_radius: f32,
31        attack_duration: f32,
32        decay_duration: f32,
33        sustain_level: f32,
34        release_duration: f32,
35        sensitivity: f32,
36        gate_threshold: f32,
37    ) -> Self {
38        let mut ret = Self {
39            center_bin: 0,
40            bin_radius: 0,
41            attack_duration,
42            decay_duration,
43            sustain_level,
44            release_duration,
45            sensitivity,
46            gate_activation_threshold: gate_threshold,
47            gate_deactivation_threshold: gate_threshold * 0.8,
48            averaging_samples: 10,
49            echo_samples: 20,
50        };
51        ret.set_filter_tune(f_center, f_radius);
52        ret
53    }
54    pub fn set_filter_tune(&mut self, f_center: f32, f_radius: f32) {
55        let f_per_bin = MAX_FREQ / FREQ_BINS as f32;
56        let center_bin = ((f_center / f_per_bin).round() as usize).min(FREQ_BINS - 1);
57        let bin_radius = (f_radius / f_per_bin).round() as usize;
58        self.center_bin = center_bin;
59        self.bin_radius = bin_radius.max(1);
60        self.gate_deactivation_threshold = self.gate_activation_threshold * 0.9;
61        //self.averaging_samples = (100f32.mul(averaging_time) as usize);
62    }
63
64    /// The band `set_filter_tune` was given, as far as the bins keep it:
65    /// center and radius in Hz.
66    pub(crate) fn filter_tune(&self) -> (f32, f32) {
67        let f_per_bin = MAX_FREQ / FREQ_BINS as f32;
68        (
69            self.center_bin as f32 * f_per_bin,
70            self.bin_radius as f32 * f_per_bin,
71        )
72    }
73}
74
75impl Default for SoundTriggerParams {
76    fn default() -> Self {
77        SoundTriggerParams::new(100., 50., 0.01, 0.0, 1.0, 0.1, 1., 0.5)
78    }
79}