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