1use sva_formula::filter::Shape;
4
5use crate::lower::physics::MODAL;
6use crate::overload::FINITE_DIFFERENCE as PHYSICS;
7
8pub const MAX_WIDTH: usize = 8;
10
11pub use sva_ast::JOIN;
12pub const CHANNEL: &str = "ch";
13pub const SERIES: &str = "sum";
14
15const ARITHMETIC: [&str; 21] = [
16 "sin", "cos", "exp", "log", "pow", "sqrt", "abs", "tanh", "max", "min", "saw", "square",
17 "triangle", "sat", "crop", "rand", "delta", "pv", SERIES, JOIN, CHANNEL,
18];
19
20pub const CASTS: [&str; 5] = ["sample", "fourier", "ifourier", "stft", "istft"];
22
23const WRITTEN_LAWS: [&str; 1] = ["noise"];
26
27const LAWS: [&str; WRITTEN_LAWS.len() + MODAL.len()] = {
28 let mut all = [""; WRITTEN_LAWS.len() + MODAL.len()];
29 let mut i = 0;
30 while i < WRITTEN_LAWS.len() {
31 all[i] = WRITTEN_LAWS[i];
32 i += 1;
33 }
34 let mut j = 0;
35 while j < MODAL.len() {
36 all[WRITTEN_LAWS.len() + j] = MODAL[j];
37 j += 1;
38 }
39 all
40};
41
42pub const BUILTINS: [&str; ARITHMETIC.len() + PHYSICS.len() + CASTS.len() + LAWS.len()] = {
44 let mut all = [""; ARITHMETIC.len() + PHYSICS.len() + CASTS.len() + LAWS.len()];
45 let mut i = 0;
46 while i < ARITHMETIC.len() {
47 all[i] = ARITHMETIC[i];
48 i += 1;
49 }
50 let mut j = 0;
51 while j < PHYSICS.len() {
52 all[ARITHMETIC.len() + j] = PHYSICS[j];
53 j += 1;
54 }
55 let mut k = 0;
56 while k < CASTS.len() {
57 all[ARITHMETIC.len() + PHYSICS.len() + k] = CASTS[k];
58 k += 1;
59 }
60 let mut n = 0;
61 while n < LAWS.len() {
62 all[ARITHMETIC.len() + PHYSICS.len() + CASTS.len() + n] = LAWS[n];
63 n += 1;
64 }
65 all
66};
67
68pub fn is_builtin(name: &str) -> bool {
69 Shape::from_name(name).is_some() || BUILTINS.contains(&name)
70}
71
72const NO_NAMED: &[&str] = &[];
74const WAVE_NAMED: &[&str] = &["tol"];
75const SAT_NAMED: &[&str] = &["drive"];
76const CROP_NAMED: &[&str] = &["start", "end", "rise", "fall"];
77const RAND_NAMED: &[&str] = &["seed"];
78const DELTA_NAMED: &[&str] = &["k"];
79const STFT_NAMED: &[&str] = &["window", "hop"];
80const NOISE_NAMED: &[&str] = &["period", "color"];
81macro_rules! modal_named {
84 (one_mode $($own:literal),+ $(,)?) => {
85 &[$($own,)+ "damp_dc", "damp_freq", "vel", "at", "contact", "p", "force"]
86 };
87 ($($own:literal),+ $(,)?) => {
88 &[$($own,)+ "damp_dc", "damp_freq", "modes", "vel", "at", "contact", "p", "force"]
89 };
90}
91
92const STRING_NAMED: &[&str] = modal_named!("inharmonicity", "strike");
93const MEMBRANE_NAMED: &[&str] = modal_named!("tension", "density", "strike_x", "strike_y");
94const BAR_NAMED: &[&str] = modal_named!("thickness", "young", "density");
95const BORE_NAMED: &[&str] = modal_named!("radius", "speed", "closed");
96const ROOM_NAMED: &[&str] = modal_named!("speed");
97const HELMHOLTZ_NAMED: &[&str] =
98 modal_named!(one_mode "neck_area", "neck_length", "radius", "speed");
99const HAMMER_NAMED: &[&str] = &["at", "contact", "p", "force"];
100const FILTER_NAMED: &[&str] = &["cutoff", "q", "gain"];
101const CHAIGNE_ASKENFELT_NAMED: &[&str] = &[
102 "b",
103 "strike_pos",
104 "vel",
105 "hammer_mass",
106 "hammer_k",
107 "hammer_p",
108 "damp_dc",
109 "damp_freq",
110 "unison_count",
111 "detune",
112 "bridge_coupling",
113];
114const WILLEMSEN_BILBAO_SERAFIN_NAMED: &[&str] = &[
115 "b",
116 "bow_pos",
117 "bow_vel",
118 "bow_force",
119 "mu_s",
120 "mu_c",
121 "stribeck_vel",
122 "bristle_stiffness",
123 "bristle_damping",
124 "viscous_friction",
125 "damp_dc",
126 "damp_freq",
127];
128const DARABUNDIT_SCAVONE_NAMED: &[&str] = &[
130 "radius_in",
131 "radius_out",
132 "excite_pos",
133 "pulse_amp",
134 "pulse_width",
135 "damp_dc",
136 "damp_freq",
137 "hole1_pos",
138 "hole1_open",
139 "hole1_radius",
140 "hole1_height",
141 "hole2_pos",
142 "hole2_open",
143 "hole2_radius",
144 "hole2_height",
145 "hole3_pos",
146 "hole3_open",
147 "hole3_radius",
148 "hole3_height",
149 "hole4_pos",
150 "hole4_open",
151 "hole4_radius",
152 "hole4_height",
153 "hole5_pos",
154 "hole5_open",
155 "hole5_radius",
156 "hole5_height",
157 "hole6_pos",
158 "hole6_open",
159 "hole6_radius",
160 "hole6_height",
161];
162const RHAOUTI_CHAIGNE_JOLY_NAMED: &[&str] = &[
163 "aspect_ratio",
164 "strike_x",
165 "strike_y",
166 "vel",
167 "hammer_mass",
168 "hammer_k",
169 "hammer_p",
170 "damp_dc",
171 "damp_freq",
172];
173const CHAIGNE_DOUTAUT_NAMED: &[&str] = &[
174 "strike_pos",
175 "vel",
176 "hammer_mass",
177 "hammer_k",
178 "hammer_p",
179 "damp_dc",
180 "damp_freq",
181];
182const BOTTELDOOREN_NAMED: &[&str] = &[
183 "aspect_y",
184 "aspect_z",
185 "listener_x",
186 "listener_y",
187 "listener_z",
188 "pulse_amp",
189 "pulse_width",
190 "damp_dc",
191 "damp_freq",
192];
193
194pub fn recognized_named(name: &str) -> Option<&'static [&'static str]> {
196 if Shape::from_name(name).is_some() {
197 return Some(FILTER_NAMED);
198 }
199 Some(match name {
200 "sin" | "cos" | "exp" | "sqrt" | "abs" | "tanh" | "max" | "min" | "pow" | "log" => NO_NAMED,
201 "saw" | "square" | "triangle" => WAVE_NAMED,
202 "sat" => SAT_NAMED,
203 SERIES | "pv" => NO_NAMED,
204 "crop" => CROP_NAMED,
205 "rand" => RAND_NAMED,
206 "delta" => DELTA_NAMED,
207 "chaigne_askenfelt" => CHAIGNE_ASKENFELT_NAMED,
208 "willemsen_bilbao_serafin" => WILLEMSEN_BILBAO_SERAFIN_NAMED,
209 "darabundit_scavone" => DARABUNDIT_SCAVONE_NAMED,
210 "rhaouti_chaigne_joly" => RHAOUTI_CHAIGNE_JOLY_NAMED,
211 "chaigne_doutaut" => CHAIGNE_DOUTAUT_NAMED,
212 "botteldooren" => BOTTELDOOREN_NAMED,
213 JOIN | CHANNEL => NO_NAMED,
214 "stft" => STFT_NAMED,
215 "sample" | "fourier" | "ifourier" | "istft" => NO_NAMED,
216 "noise" => NOISE_NAMED,
217 "string" => STRING_NAMED,
218 "membrane" => MEMBRANE_NAMED,
219 "bar" => BAR_NAMED,
220 "bore" => BORE_NAMED,
221 "room" => ROOM_NAMED,
222 "helmholtz" => HELMHOLTZ_NAMED,
223 "hammer_pulse" => HAMMER_NAMED,
224 _ => return None,
225 })
226}