sound_to_patch/preset/
catalogue.rs1use std::fmt;
20
21use crate::preset::vital;
22use crate::synth::{Synth, SynthError};
23
24#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
26pub enum Layer {
27 Pitch,
29 Oscillator,
31 Unison,
33 Filter,
35 Envelope,
37 Modulation,
39 Distortion,
41 Space,
43}
44
45impl Layer {
46 pub const ALL: [Self; 8] = [
48 Self::Pitch,
49 Self::Oscillator,
50 Self::Unison,
51 Self::Filter,
52 Self::Envelope,
53 Self::Modulation,
54 Self::Distortion,
55 Self::Space,
56 ];
57
58 #[must_use]
60 pub fn as_str(self) -> &'static str {
61 match self {
62 Self::Pitch => "pitch",
63 Self::Oscillator => "oscillator",
64 Self::Unison => "unison",
65 Self::Filter => "filter",
66 Self::Envelope => "envelope",
67 Self::Modulation => "modulation",
68 Self::Distortion => "distortion",
69 Self::Space => "space",
70 }
71 }
72
73 #[must_use]
75 pub fn title(self) -> &'static str {
76 match self {
77 Self::Pitch => "Pitch and glide",
78 Self::Oscillator => "Oscillator source",
79 Self::Unison => "Unison and width",
80 Self::Filter => "Filter",
81 Self::Envelope => "Envelopes",
82 Self::Modulation => "Modulation",
83 Self::Distortion => "Distortion",
84 Self::Space => "Space and effects",
85 }
86 }
87}
88
89impl fmt::Display for Layer {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 f.pad(self.as_str())
92 }
93}
94
95#[derive(Clone, Debug, PartialEq, Eq)]
97pub struct Placement {
98 pub layer: Option<Layer>,
101 pub pattern: String,
104 pub instance: Option<String>,
106}
107
108pub fn placement(synth: Synth, key: &str) -> Result<Placement, SynthError> {
115 match synth.ready()? {
116 Synth::Vital => vital::placement(key).ok_or_else(|| SynthError::BrokenData {
117 synth,
118 cause: format!("the reference map places no layer for {key:?}"),
119 }),
120 Synth::Serum2 => Err(SynthError::NotBuilt(synth)),
121 }
122}
123
124pub fn unread_keys(synth: Synth) -> Result<&'static [&'static str], SynthError> {
131 match synth.ready()? {
132 Synth::Vital => Ok(&vital::RETAIL_ONLY_KEYS),
133 Synth::Serum2 => Err(SynthError::NotBuilt(synth)),
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use crate::preset::registry::registry_for;
141
142 #[test]
143 fn every_key_of_a_ready_synth_has_a_place() {
144 for synth in Synth::READY {
145 let registry = registry_for(synth).unwrap();
146 for spec in registry.iter() {
147 let place = placement(synth, &spec.key).unwrap();
148 assert!(!place.pattern.is_empty(), "{}", spec.key);
149 }
150 }
151 }
152
153 #[test]
154 fn serum2_is_not_ready() {
155 assert!(matches!(
156 placement(Synth::Serum2, "a"),
157 Err(SynthError::NotBuilt(Synth::Serum2))
158 ));
159 }
160}