gled_model/sound/
trigger_ref.rs1use std::collections::HashMap;
8
9use serde::{Deserialize, Serialize};
10use uuid::Uuid;
11
12use super::trigger_params::{FREQ_BINS, SoundTriggerParams};
13
14#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
17#[serde(from = "SavedTrigger")]
18pub struct SoundTriggerRef {
19 pub id: Uuid,
20 pub params: SoundTriggerParams,
21 pub f_center: f32,
22 pub f_radius: f32,
23 pub(crate) averaging_time: f32,
24}
25
26#[derive(Deserialize)]
30struct SavedTrigger {
31 #[serde(default = "Uuid::new_v4")]
32 id: Uuid,
33 params: SoundTriggerParams,
34 f_center: Option<f32>,
35 f_radius: Option<f32>,
36 averaging_time: f32,
37}
38
39impl From<SavedTrigger> for SoundTriggerRef {
40 fn from(saved: SavedTrigger) -> Self {
41 let (f_center, f_radius) = saved.params.filter_tune();
42 Self {
43 id: saved.id,
44 params: saved.params,
45 f_center: saved.f_center.unwrap_or(f_center),
46 f_radius: saved.f_radius.unwrap_or(f_radius),
47 averaging_time: saved.averaging_time,
48 }
49 }
50}
51
52impl Default for SoundTriggerRef {
53 fn default() -> Self {
54 Self {
55 id: Uuid::new_v4(),
56 params: SoundTriggerParams::default(),
57 f_center: 8200.,
58 f_radius: 990.,
59 averaging_time: 0.1,
60 }
61 }
62}
63
64pub trait SoundLevels {
68 fn level(&self, id: &Uuid) -> f32;
70 fn spectrum_bytes(&self) -> [u8; FREQ_BINS * 4];
72}
73
74pub type SoundTriggerSet = HashMap<Uuid, SoundTriggerParams>;
76
77pub trait CollectSoundTriggers {
79 fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet);
82}
83
84impl CollectSoundTriggers for SoundTriggerRef {
85 fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet) {
86 triggers.entry(self.id).or_insert(self.params);
87 }
88}
89
90impl<T: CollectSoundTriggers> CollectSoundTriggers for Option<T> {
91 fn collect_sound_triggers(&self, triggers: &mut SoundTriggerSet) {
92 if let Some(value) = self {
93 value.collect_sound_triggers(triggers);
94 }
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn loads_triggers_saved_without_an_id() {
104 let json = serde_json::to_string(&SoundTriggerRef::default()).expect("serializes");
105 let mut value: serde_json::Value = serde_json::from_str(&json).expect("json");
106 value.as_object_mut().expect("object").remove("id");
107 let old: SoundTriggerRef = serde_json::from_value(value).expect("loads without id");
108 assert_eq!(old.f_center, 8200.);
109 }
110
111 #[test]
112 fn loads_triggers_saved_with_bins() {
113 let json = serde_json::to_string(&SoundTriggerRef::default()).expect("serializes");
114 let mut value: serde_json::Value = serde_json::from_str(&json).expect("json");
115 let object = value.as_object_mut().expect("object");
116 object.remove("f_center");
117 object.remove("f_radius");
118 object.insert("center_bin".to_string(), 134.29.into());
119 object.insert("window_bins".to_string(), 16.0.into());
120 let old: SoundTriggerRef = serde_json::from_value(value).expect("loads with bins");
121 let mut params = SoundTriggerParams::default();
122 params.set_filter_tune(old.f_center, old.f_radius);
123 assert_eq!(params, old.params);
124 }
125
126 #[test]
127 fn copies_share_their_trigger() {
128 let trigger = SoundTriggerRef::default();
129 let mut set = SoundTriggerSet::new();
130 trigger.collect_sound_triggers(&mut set);
131 trigger.clone().collect_sound_triggers(&mut set);
132 assert_eq!(set.len(), 1);
133 }
134}